diff --git a/app/views/documents/show.html.erb b/app/views/documents/show.html.erb index 38ed8819..a7bbc313 100644 --- a/app/views/documents/show.html.erb +++ b/app/views/documents/show.html.erb @@ -1,3 +1,5 @@ +
+
<% if User.current.allowed_to?(:edit_documents, @project) %> <%= link_to l(:button_edit), edit_document_path(@document), :class => 'icon icon-edit', :accesskey => accesskey(:edit) %> @@ -7,24 +9,13 @@ <% end %>
- - - - - - - -

<%=h @document.title %>

-
- <%= textilizable @document.description, :attachments => @document.attachments %> -
-

<%= format_date @document.created_on %>

+<%= textilizable @document, :description, :attachments => @document.attachments %> +

<%= l(:label_attachment_plural) %>

@@ -42,3 +33,4 @@ <% end %> <% html_title @document.title -%> + diff --git a/lib/redcloth3.rb b/lib/redcloth3.rb index b0bda81a..f4d880fb 100644 --- a/lib/redcloth3.rb +++ b/lib/redcloth3.rb @@ -31,7 +31,7 @@ # # == Sample Textile Text # -# h3. This is a title +# h2. This is a title # # h3. This is a subhead # @@ -129,7 +129,7 @@ # # Will become: # -# ACLU +# ACLU # # == Adding Tables # @@ -152,7 +152,7 @@ # # doc = RedCloth.new " # -# h3. Test document +# h2. Test document # # Just a simple test." # @@ -166,221 +166,221 @@ class RedCloth3 < String - VERSION = '3.0.4' - DEFAULT_RULES = [:textile, :markdown] + VERSION = '3.0.4' + DEFAULT_RULES = [:textile, :markdown] - # - # Two accessor for setting security restrictions. - # - # This is a nice thing if you're using RedCloth for - # formatting in public places (e.g. Wikis) where you - # don't want users to abuse HTML for bad things. - # - # If +:filter_html+ is set, HTML which wasn't - # created by the Textile processor will be escaped. - # - # If +:filter_styles+ is set, it will also disable - # the style markup specifier. ('{color: red}') - # - attr_accessor :filter_html, :filter_styles + # + # Two accessor for setting security restrictions. + # + # This is a nice thing if you're using RedCloth for + # formatting in public places (e.g. Wikis) where you + # don't want users to abuse HTML for bad things. + # + # If +:filter_html+ is set, HTML which wasn't + # created by the Textile processor will be escaped. + # + # If +:filter_styles+ is set, it will also disable + # the style markup specifier. ('{color: red}') + # + attr_accessor :filter_html, :filter_styles - # - # Accessor for toggling hard breaks. - # - # If +:hard_breaks+ is set, single newlines will - # be converted to HTML break tags. This is the - # default behavior for traditional RedCloth. - # - attr_accessor :hard_breaks + # + # Accessor for toggling hard breaks. + # + # If +:hard_breaks+ is set, single newlines will + # be converted to HTML break tags. This is the + # default behavior for traditional RedCloth. + # + attr_accessor :hard_breaks - # Accessor for toggling lite mode. - # - # In lite mode, block-level rules are ignored. This means - # that tables, paragraphs, lists, and such aren't available. - # Only the inline markup for bold, italics, entities and so on. - # - # r = RedCloth.new( "And then? She *fell*!", [:lite_mode] ) - # r.to_html - # #=> "And then? She fell!" - # - attr_accessor :lite_mode + # Accessor for toggling lite mode. + # + # In lite mode, block-level rules are ignored. This means + # that tables, paragraphs, lists, and such aren't available. + # Only the inline markup for bold, italics, entities and so on. + # + # r = RedCloth.new( "And then? She *fell*!", [:lite_mode] ) + # r.to_html + # #=> "And then? She fell!" + # + attr_accessor :lite_mode - # - # Accessor for toggling span caps. - # - # Textile places `span' tags around capitalized - # words by default, but this wreaks havoc on Wikis. - # If +:no_span_caps+ is set, this will be - # suppressed. - # - attr_accessor :no_span_caps + # + # Accessor for toggling span caps. + # + # Textile places `span' tags around capitalized + # words by default, but this wreaks havoc on Wikis. + # If +:no_span_caps+ is set, this will be + # suppressed. + # + attr_accessor :no_span_caps - # - # Establishes the markup predence. Available rules include: - # - # == Textile Rules - # - # The following textile rules can be set individually. Or add the complete - # set of rules with the single :textile rule, which supplies the rule set in - # the following precedence: - # - # refs_textile:: Textile references (i.e. [hobix]http://hobix.com/) - # block_textile_table:: Textile table block structures - # block_textile_lists:: Textile list structures - # block_textile_prefix:: Textile blocks with prefixes (i.e. bq., h3., etc.) - # inline_textile_image:: Textile inline images - # inline_textile_link:: Textile inline links - # inline_textile_span:: Textile inline spans - # glyphs_textile:: Textile entities (such as em-dashes and smart quotes) - # - # == Markdown - # - # refs_markdown:: Markdown references (for example: [hobix]: http://hobix.com/) - # block_markdown_setext:: Markdown setext headers - # block_markdown_atx:: Markdown atx headers - # block_markdown_rule:: Markdown horizontal rules - # block_markdown_bq:: Markdown blockquotes - # block_markdown_lists:: Markdown lists - # inline_markdown_link:: Markdown links - attr_accessor :rules + # + # Establishes the markup predence. Available rules include: + # + # == Textile Rules + # + # The following textile rules can be set individually. Or add the complete + # set of rules with the single :textile rule, which supplies the rule set in + # the following precedence: + # + # refs_textile:: Textile references (i.e. [hobix]http://hobix.com/) + # block_textile_table:: Textile table block structures + # block_textile_lists:: Textile list structures + # block_textile_prefix:: Textile blocks with prefixes (i.e. bq., h2., etc.) + # inline_textile_image:: Textile inline images + # inline_textile_link:: Textile inline links + # inline_textile_span:: Textile inline spans + # glyphs_textile:: Textile entities (such as em-dashes and smart quotes) + # + # == Markdown + # + # refs_markdown:: Markdown references (for example: [hobix]: http://hobix.com/) + # block_markdown_setext:: Markdown setext headers + # block_markdown_atx:: Markdown atx headers + # block_markdown_rule:: Markdown horizontal rules + # block_markdown_bq:: Markdown blockquotes + # block_markdown_lists:: Markdown lists + # inline_markdown_link:: Markdown links + attr_accessor :rules - # Returns a new RedCloth object, based on _string_ and - # enforcing all the included _restrictions_. - # - # r = RedCloth.new( "h1. A bold man", [:filter_html] ) - # r.to_html - # #=>"

A <b>bold</b> man

" - # - def initialize( string, restrictions = [] ) - restrictions.each { |r| method( "#{ r }=" ).call( true ) } - super( string ) + # Returns a new RedCloth object, based on _string_ and + # enforcing all the included _restrictions_. + # + # r = RedCloth.new( "h1. A bold man", [:filter_html] ) + # r.to_html + # #=>"

A <b>bold</b> man

" + # + def initialize( string, restrictions = [] ) + restrictions.each { |r| method( "#{ r }=" ).call( true ) } + super( string ) + end + + # + # Generates HTML from the Textile contents. + # + # r = RedCloth.new( "And then? She *fell*!" ) + # r.to_html( true ) + # #=>"And then? She fell!" + # + def to_html( *rules ) + rules = DEFAULT_RULES if rules.empty? + # make our working copy + text = self.dup + + @urlrefs = {} + @shelf = [] + textile_rules = [:block_textile_table, :block_textile_lists, + :block_textile_prefix, :inline_textile_image, :inline_textile_link, + :inline_textile_code, :inline_textile_span, :glyphs_textile] + markdown_rules = [:refs_markdown, :block_markdown_setext, :block_markdown_atx, :block_markdown_rule, + :block_markdown_bq, :block_markdown_lists, + :inline_markdown_reflink, :inline_markdown_link] + @rules = rules.collect do |rule| + case rule + when :markdown + markdown_rules + when :textile + textile_rules + else + rule + end + end.flatten + + # standard clean up + incoming_entities text + clean_white_space text + + # start processor + @pre_list = [] + rip_offtags text + no_textile text + escape_html_tags text + # need to do this before #hard_break and #blocks + block_textile_quotes text unless @lite_mode + hard_break text + unless @lite_mode + refs text + blocks text end + inline text + smooth_offtags text - # - # Generates HTML from the Textile contents. - # - # r = RedCloth.new( "And then? She *fell*!" ) - # r.to_html( true ) - # #=>"And then? She fell!" - # - def to_html( *rules ) - rules = DEFAULT_RULES if rules.empty? - # make our working copy - text = self.dup - - @urlrefs = {} - @shelf = [] - textile_rules = [:block_textile_table, :block_textile_lists, - :block_textile_prefix, :inline_textile_image, :inline_textile_link, - :inline_textile_code, :inline_textile_span, :glyphs_textile] - markdown_rules = [:refs_markdown, :block_markdown_setext, :block_markdown_atx, :block_markdown_rule, - :block_markdown_bq, :block_markdown_lists, - :inline_markdown_reflink, :inline_markdown_link] - @rules = rules.collect do |rule| - case rule - when :markdown - markdown_rules - when :textile - textile_rules - else - rule - end - end.flatten + retrieve text - # standard clean up - incoming_entities text - clean_white_space text + text.gsub!( /<\/?notextile>/, '' ) + text.gsub!( /x%x%/, '&' ) + clean_html text if filter_html + text.strip! + text - # start processor - @pre_list = [] - rip_offtags text - no_textile text - escape_html_tags text - # need to do this before #hard_break and #blocks - block_textile_quotes text unless @lite_mode - hard_break text - unless @lite_mode - refs text - blocks text - end - inline text - smooth_offtags text + end - retrieve text + ####### + private + ####### + # + # Mapping of 8-bit ASCII codes to HTML numerical entity equivalents. + # (from PyTextile) + # + TEXTILE_TAGS = - text.gsub!( /<\/?notextile>/, '' ) - text.gsub!( /x%x%/, '&' ) - clean_html text if filter_html - text.strip! - text + [[128, 8364], [129, 0], [130, 8218], [131, 402], [132, 8222], [133, 8230], + [134, 8224], [135, 8225], [136, 710], [137, 8240], [138, 352], [139, 8249], + [140, 338], [141, 0], [142, 0], [143, 0], [144, 0], [145, 8216], [146, 8217], + [147, 8220], [148, 8221], [149, 8226], [150, 8211], [151, 8212], [152, 732], + [153, 8482], [154, 353], [155, 8250], [156, 339], [157, 0], [158, 0], [159, 376]]. - end + collect! do |a, b| + [a.chr, ( b.zero? and "" or "&#{ b };" )] + end - ####### - private - ####### - # - # Mapping of 8-bit ASCII codes to HTML numerical entity equivalents. - # (from PyTextile) - # - TEXTILE_TAGS = + # + # Regular expressions to convert to HTML. + # + A_HLGN = /(?:(?:<>|<|>|\=|[()]+)+)/ + A_VLGN = /[\-^~]/ + C_CLAS = '(?:\([^")]+\))' + C_LNGE = '(?:\[[^"\[\]]+\])' + C_STYL = '(?:\{[^"}]+\})' + S_CSPN = '(?:\\\\\d+)' + S_RSPN = '(?:/\d+)' + A = "(?:#{A_HLGN}?#{A_VLGN}?|#{A_VLGN}?#{A_HLGN}?)" + S = "(?:#{S_CSPN}?#{S_RSPN}|#{S_RSPN}?#{S_CSPN}?)" + C = "(?:#{C_CLAS}?#{C_STYL}?#{C_LNGE}?|#{C_STYL}?#{C_LNGE}?#{C_CLAS}?|#{C_LNGE}?#{C_STYL}?#{C_CLAS}?)" + # PUNCT = Regexp::quote( '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~' ) + PUNCT = Regexp::quote( '!"#$%&\'*+,-./:;=?@\\^_`|~' ) + PUNCT_NOQ = Regexp::quote( '!"#$&\',./:;=?@\\`|' ) + PUNCT_Q = Regexp::quote( '*-_+^~%' ) + HYPERLINK = '(\S+?)([^\w\s/;=\?]*?)(?=\s|<|$)' - [[128, 8364], [129, 0], [130, 8218], [131, 402], [132, 8222], [133, 8230], - [134, 8224], [135, 8225], [136, 710], [137, 8240], [138, 352], [139, 8249], - [140, 338], [141, 0], [142, 0], [143, 0], [144, 0], [145, 8216], [146, 8217], - [147, 8220], [148, 8221], [149, 8226], [150, 8211], [151, 8212], [152, 732], - [153, 8482], [154, 353], [155, 8250], [156, 339], [157, 0], [158, 0], [159, 376]]. + # Text markup tags, don't conflict with block tags + SIMPLE_HTML_TAGS = [ + 'tt', 'b', 'i', 'big', 'small', 'em', 'strong', 'dfn', 'code', + 'samp', 'kbd', 'var', 'cite', 'abbr', 'acronym', 'a', 'img', 'br', + 'br', 'map', 'q', 'sub', 'sup', 'span', 'bdo' + ] - collect! do |a, b| - [a.chr, ( b.zero? and "" or "&#{ b };" )] - end + QTAGS = [ + ['**', 'b', :limit], + ['*', 'strong', :limit], + ['??', 'cite', :limit], + ['-', 'del', :limit], + ['__', 'i', :limit], + ['_', 'em', :limit], + ['%', 'span', :limit], + ['+', 'ins', :limit], + ['^', 'sup', :limit], + ['~', 'sub', :limit] + ] + QTAGS_JOIN = QTAGS.map {|rc, ht, rtype| Regexp::quote rc}.join('|') - # - # Regular expressions to convert to HTML. - # - A_HLGN = /(?:(?:<>|<|>|\=|[()]+)+)/ - A_VLGN = /[\-^~]/ - C_CLAS = '(?:\([^")]+\))' - C_LNGE = '(?:\[[^"\[\]]+\])' - C_STYL = '(?:\{[^"}]+\})' - S_CSPN = '(?:\\\\\d+)' - S_RSPN = '(?:/\d+)' - A = "(?:#{A_HLGN}?#{A_VLGN}?|#{A_VLGN}?#{A_HLGN}?)" - S = "(?:#{S_CSPN}?#{S_RSPN}|#{S_RSPN}?#{S_CSPN}?)" - C = "(?:#{C_CLAS}?#{C_STYL}?#{C_LNGE}?|#{C_STYL}?#{C_LNGE}?#{C_CLAS}?|#{C_LNGE}?#{C_STYL}?#{C_CLAS}?)" - # PUNCT = Regexp::quote( '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~' ) - PUNCT = Regexp::quote( '!"#$%&\'*+,-./:;=?@\\^_`|~' ) - PUNCT_NOQ = Regexp::quote( '!"#$&\',./:;=?@\\`|' ) - PUNCT_Q = Regexp::quote( '*-_+^~%' ) - HYPERLINK = '(\S+?)([^\w\s/;=\?]*?)(?=\s|<|$)' - - # Text markup tags, don't conflict with block tags - SIMPLE_HTML_TAGS = [ - 'tt', 'b', 'i', 'big', 'small', 'em', 'strong', 'dfn', 'code', - 'samp', 'kbd', 'var', 'cite', 'abbr', 'acronym', 'a', 'img', 'br', - 'br', 'map', 'q', 'sub', 'sup', 'span', 'bdo' - ] - - QTAGS = [ - ['**', 'b', :limit], - ['*', 'strong', :limit], - ['??', 'cite', :limit], - ['-', 'del', :limit], - ['__', 'i', :limit], - ['_', 'em', :limit], - ['%', 'span', :limit], - ['+', 'ins', :limit], - ['^', 'sup', :limit], - ['~', 'sub', :limit] - ] - QTAGS_JOIN = QTAGS.map {|rc, ht, rtype| Regexp::quote rc}.join('|') - - QTAGS.collect! do |rc, ht, rtype| - rcq = Regexp::quote rc - re = - case rtype - when :limit - /(^|[>\s\(]) # sta + QTAGS.collect! do |rc, ht, rtype| + rcq = Regexp::quote rc + re = + case rtype + when :limit + /(^|[>\s\(]) # sta (?!\-\-) (#{QTAGS_JOIN}|) # oqs (#{rcq}) # qtag @@ -389,423 +389,423 @@ class RedCloth3 < String #{rcq} (#{QTAGS_JOIN}|) # oqa (?=[[:punct:]]|<|\s|\)|$)/x - else - /(#{rcq}) + else + /(#{rcq}) (#{C}) (?::(\S+))? (\w|[^\s\-].*?[^\s\-]) - #{rcq}/xm - end - [rc, ht, re, rtype] + #{rcq}/xm + end + [rc, ht, re, rtype] + end + + # Elements to handle + GLYPHS = [ + # [ /([^\s\[{(>])?\'([dmst]\b|ll\b|ve\b|\s|:|$)/, '\1’\2' ], # single closing + # [ /([^\s\[{(>#{PUNCT_Q}][#{PUNCT_Q}]*)\'/, '\1’' ], # single closing + # [ /\'(?=[#{PUNCT_Q}]*(s\b|[\s#{PUNCT_NOQ}]))/, '’' ], # single closing + # [ /\'/, '‘' ], # single opening + # [ //, '>' ], # greater-than + # [ /([^\s\[{(])?"(\s|:|$)/, '\1”\2' ], # double closing + # [ /([^\s\[{(>#{PUNCT_Q}][#{PUNCT_Q}]*)"/, '\1”' ], # double closing + # [ /"(?=[#{PUNCT_Q}]*[\s#{PUNCT_NOQ}])/, '”' ], # double closing + # [ /"/, '“' ], # double opening + # [ /\b( )?\.{3}/, '\1…' ], # ellipsis + # [ /\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])/, '\1' ], # 3+ uppercase acronym + # [ /(^|[^"][>\s])([A-Z][A-Z0-9 ]+[A-Z0-9])([^\2\3', :no_span_caps ], # 3+ uppercase caps + # [ /(\.\s)?\s?--\s?/, '\1—' ], # em dash + # [ /\s->\s/, ' → ' ], # right arrow + # [ /\s-\s/, ' – ' ], # en dash + # [ /(\d+) ?x ?(\d+)/, '\1×\2' ], # dimension sign + # [ /\b ?[(\[]TM[\])]/i, '™' ], # trademark + # [ /\b ?[(\[]R[\])]/i, '®' ], # registered + # [ /\b ?[(\[]C[\])]/i, '©' ] # copyright + ] + + H_ALGN_VALS = { + '<' => 'left', + '=' => 'center', + '>' => 'right', + '<>' => 'justify' + } + + V_ALGN_VALS = { + '^' => 'top', + '-' => 'middle', + '~' => 'bottom' + } + + # + # Flexible HTML escaping + # + def htmlesc( str, mode=:Quotes ) + if str + str.gsub!( '&', '&' ) + str.gsub!( '"', '"' ) if mode != :NoQuotes + str.gsub!( "'", ''' ) if mode == :Quotes + str.gsub!( '<', '<') + str.gsub!( '>', '>') + end + str + end + + # Search and replace for Textile glyphs (quotes, dashes, other symbols) + def pgl( text ) + #GLYPHS.each do |re, resub, tog| + # next if tog and method( tog ).call + # text.gsub! re, resub + #end + text.gsub!(/\b([A-Z][A-Z0-9]{1,})\b(?:[(]([^)]*)[)])/) do |m| + "#{$1}" + end + end + + # Parses Textile attribute lists and builds an HTML attribute string + def pba( text_in, element = "" ) + + return '' unless text_in + + style = [] + text = text_in.dup + if element == 'td' + colspan = $1 if text =~ /\\(\d+)/ + rowspan = $1 if text =~ /\/(\d+)/ + style << "vertical-align:#{ v_align( $& ) };" if text =~ A_VLGN end - # Elements to handle - GLYPHS = [ - # [ /([^\s\[{(>])?\'([dmst]\b|ll\b|ve\b|\s|:|$)/, '\1’\2' ], # single closing - # [ /([^\s\[{(>#{PUNCT_Q}][#{PUNCT_Q}]*)\'/, '\1’' ], # single closing - # [ /\'(?=[#{PUNCT_Q}]*(s\b|[\s#{PUNCT_NOQ}]))/, '’' ], # single closing - # [ /\'/, '‘' ], # single opening - # [ //, '>' ], # greater-than - # [ /([^\s\[{(])?"(\s|:|$)/, '\1”\2' ], # double closing - # [ /([^\s\[{(>#{PUNCT_Q}][#{PUNCT_Q}]*)"/, '\1”' ], # double closing - # [ /"(?=[#{PUNCT_Q}]*[\s#{PUNCT_NOQ}])/, '”' ], # double closing - # [ /"/, '“' ], # double opening - # [ /\b( )?\.{3}/, '\1…' ], # ellipsis - # [ /\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])/, '\1' ], # 3+ uppercase acronym - # [ /(^|[^"][>\s])([A-Z][A-Z0-9 ]+[A-Z0-9])([^\2\3', :no_span_caps ], # 3+ uppercase caps - # [ /(\.\s)?\s?--\s?/, '\1—' ], # em dash - # [ /\s->\s/, ' → ' ], # right arrow - # [ /\s-\s/, ' – ' ], # en dash - # [ /(\d+) ?x ?(\d+)/, '\1×\2' ], # dimension sign - # [ /\b ?[(\[]TM[\])]/i, '™' ], # trademark - # [ /\b ?[(\[]R[\])]/i, '®' ], # registered - # [ /\b ?[(\[]C[\])]/i, '©' ] # copyright - ] + if text.sub!( /\{([^"}]*)\}/, '' ) && !filter_styles + sanitized = sanitize_styles($1) + style << "#{ sanitized };" unless sanitized.blank? + end - H_ALGN_VALS = { - '<' => 'left', - '=' => 'center', - '>' => 'right', - '<>' => 'justify' - } + lang = $1 if + text.sub!( /\[([^)]+?)\]/, '' ) - V_ALGN_VALS = { - '^' => 'top', - '-' => 'middle', - '~' => 'bottom' - } + cls = $1 if + text.sub!( /\(([^()]+?)\)/, '' ) - # - # Flexible HTML escaping - # - def htmlesc( str, mode=:Quotes ) - if str - str.gsub!( '&', '&' ) - str.gsub!( '"', '"' ) if mode != :NoQuotes - str.gsub!( "'", ''' ) if mode == :Quotes - str.gsub!( '<', '<') - str.gsub!( '>', '>') + style << "padding-left:#{ $1.length }em;" if + text.sub!( /([(]+)/, '' ) + + style << "padding-right:#{ $1.length }em;" if text.sub!( /([)]+)/, '' ) + + style << "text-align:#{ h_align( $& ) };" if text =~ A_HLGN + + cls, id = $1, $2 if cls =~ /^(.*?)#(.*)$/ + + atts = '' + atts << " style=\"#{ style.join }\"" unless style.empty? + atts << " class=\"#{ cls }\"" unless cls.to_s.empty? + atts << " lang=\"#{ lang }\"" if lang + atts << " id=\"#{ id }\"" if id + atts << " colspan=\"#{ colspan }\"" if colspan + atts << " rowspan=\"#{ rowspan }\"" if rowspan + + atts + end + + STYLES_RE = /^(color|width|height|border|background|padding|margin|font|text|float)(-[a-z]+)*:\s*((\d+%?|\d+px|\d+(\.\d+)?em|#[0-9a-f]+|[a-z]+)\s*)+$/i + + def sanitize_styles(str) + styles = str.split(";").map(&:strip) + styles.reject! do |style| + !style.match(STYLES_RE) + end + styles.join(";") + end + + TABLE_RE = /^(?:table(_?#{S}#{A}#{C})\. ?\n)?^(#{A}#{C}\.? ?\|.*?\|)(\n\n|\Z)/m + + # Parses a Textile table block, building HTML from the result. + def block_textile_table( text ) + text.gsub!( TABLE_RE ) do |matches| + + tatts, fullrow = $~[1..2] + tatts = pba( tatts, 'table' ) + tatts = shelve( tatts ) if tatts + rows = [] + fullrow.gsub!(/([^|])\n/, "\\1
") + fullrow.each_line do |row| + ratts, row = pba( $1, 'tr' ), $2 if row =~ /^(#{A}#{C}\. )(.*)/m + cells = [] + row.split( /(\|)(?![^\[\|]*\]\])/ )[1..-2].each do |cell| + next if cell == '|' + ctyp = 'd' + ctyp = 'h' if cell =~ /^_/ + + catts = '' + catts, cell = pba( $1, 'td' ), $2 if cell =~ /^(_?#{S}#{A}#{C}\. ?)(.*)/ + + catts = shelve( catts ) if catts + cells << "\t\t\t#{ cell }" + end + ratts = shelve( ratts ) if ratts + rows << "\t\t\n#{ cells.join( "\n" ) }\n\t\t" end - str + "\t\n#{ rows.join( "\n" ) }\n\t\n\n" end + end - # Search and replace for Textile glyphs (quotes, dashes, other symbols) - def pgl( text ) - #GLYPHS.each do |re, resub, tog| - # next if tog and method( tog ).call - # text.gsub! re, resub - #end - text.gsub!(/\b([A-Z][A-Z0-9]{1,})\b(?:[(]([^)]*)[)])/) do |m| - "#{$1}" - end - end + LISTS_RE = /^([#*]+?#{C} .*?)$(?![^#*])/m + LISTS_CONTENT_RE = /^([#*]+)(#{A}#{C}) (.*)$/m - # Parses Textile attribute lists and builds an HTML attribute string - def pba( text_in, element = "" ) - - return '' unless text_in - - style = [] - text = text_in.dup - if element == 'td' - colspan = $1 if text =~ /\\(\d+)/ - rowspan = $1 if text =~ /\/(\d+)/ - style << "vertical-align:#{ v_align( $& ) };" if text =~ A_VLGN - end - - if text.sub!( /\{([^"}]*)\}/, '' ) && !filter_styles - sanitized = sanitize_styles($1) - style << "#{ sanitized };" unless sanitized.blank? - end - - lang = $1 if - text.sub!( /\[([^)]+?)\]/, '' ) - - cls = $1 if - text.sub!( /\(([^()]+?)\)/, '' ) - - style << "padding-left:#{ $1.length }em;" if - text.sub!( /([(]+)/, '' ) - - style << "padding-right:#{ $1.length }em;" if text.sub!( /([)]+)/, '' ) - - style << "text-align:#{ h_align( $& ) };" if text =~ A_HLGN - - cls, id = $1, $2 if cls =~ /^(.*?)#(.*)$/ - - atts = '' - atts << " style=\"#{ style.join }\"" unless style.empty? - atts << " class=\"#{ cls }\"" unless cls.to_s.empty? - atts << " lang=\"#{ lang }\"" if lang - atts << " id=\"#{ id }\"" if id - atts << " colspan=\"#{ colspan }\"" if colspan - atts << " rowspan=\"#{ rowspan }\"" if rowspan - - atts - end - - STYLES_RE = /^(color|width|height|border|background|padding|margin|font|text|float)(-[a-z]+)*:\s*((\d+%?|\d+px|\d+(\.\d+)?em|#[0-9a-f]+|[a-z]+)\s*)+$/i - - def sanitize_styles(str) - styles = str.split(";").map(&:strip) - styles.reject! do |style| - !style.match(STYLES_RE) - end - styles.join(";") - end - - TABLE_RE = /^(?:table(_?#{S}#{A}#{C})\. ?\n)?^(#{A}#{C}\.? ?\|.*?\|)(\n\n|\Z)/m - - # Parses a Textile table block, building HTML from the result. - def block_textile_table( text ) - text.gsub!( TABLE_RE ) do |matches| - - tatts, fullrow = $~[1..2] - tatts = pba( tatts, 'table' ) - tatts = shelve( tatts ) if tatts - rows = [] - - fullrow.each_line do |row| - ratts, row = pba( $1, 'tr' ), $2 if row =~ /^(#{A}#{C}\. )(.*)/m - cells = [] - row.split( /(\|)(?![^\[\|]*\]\])/ )[1..-2].each do |cell| - next if cell == '|' - ctyp = 'd' - ctyp = 'h' if cell =~ /^_/ - - catts = '' - catts, cell = pba( $1, 'td' ), $2 if cell =~ /^(_?#{S}#{A}#{C}\. ?)(.*)/ - - catts = shelve( catts ) if catts - cells << "\t\t\t#{ cell }" - end - ratts = shelve( ratts ) if ratts - rows << "\t\t\n#{ cells.join( "\n" ) }\n\t\t" + # Parses Textile lists and generates HTML + def block_textile_lists( text ) + text.gsub!( LISTS_RE ) do |match| + lines = match.split( /\n/ ) + last_line = -1 + depth = [] + lines.each_with_index do |line, line_id| + if line =~ LISTS_CONTENT_RE + tl,atts,content = $~[1..3] + if depth.last + if depth.last.length > tl.length + (depth.length - 1).downto(0) do |i| + break if depth[i].length == tl.length + lines[line_id - 1] << "\n\t\n\t" + depth.pop + end end - "\t\n#{ rows.join( "\n" ) }\n\t\n\n" - end - end - - LISTS_RE = /^([#*]+?#{C} .*?)$(?![^#*])/m - LISTS_CONTENT_RE = /^([#*]+)(#{A}#{C}) (.*)$/m - - # Parses Textile lists and generates HTML - def block_textile_lists( text ) - text.gsub!( LISTS_RE ) do |match| - lines = match.split( /\n/ ) - last_line = -1 - depth = [] - lines.each_with_index do |line, line_id| - if line =~ LISTS_CONTENT_RE - tl,atts,content = $~[1..3] - if depth.last - if depth.last.length > tl.length - (depth.length - 1).downto(0) do |i| - break if depth[i].length == tl.length - lines[line_id - 1] << "\n\t\n\t" - depth.pop - end - end - if depth.last and depth.last.length == tl.length - lines[line_id - 1] << '' - end - end - unless depth.last == tl - depth << tl - atts = pba( atts ) - atts = shelve( atts ) if atts - lines[line_id] = "\t<#{ lT(tl) }l#{ atts }>\n\t
  • #{ content }" - else - lines[line_id] = "\t\t
  • #{ content }" - end - last_line = line_id - - else - last_line = line_id - end - if line_id - last_line > 1 or line_id == lines.length - 1 - while v = depth.pop - lines[last_line] << "
  • \n\t" - end - end + if depth.last and depth.last.length == tl.length + lines[line_id - 1] << '' end - lines.join( "\n" ) - end - end - - QUOTES_RE = /(^>+([^\n]*?)(\n|$))+/m - QUOTES_CONTENT_RE = /^([> ]+)(.*)$/m - - def block_textile_quotes( text ) - text.gsub!( QUOTES_RE ) do |match| - lines = match.split( /\n/ ) - quotes = '' - indent = 0 - lines.each do |line| - line =~ QUOTES_CONTENT_RE - bq,content = $1, $2 - l = bq.count('>') - if l != indent - quotes << ("\n\n" + (l>indent ? '
    ' * (l-indent) : '
    ' * (indent-l)) + "\n\n") - indent = l end - quotes << (content + "\n") - end - quotes << ("\n" + '' * indent + "\n\n") - quotes - end - end + unless depth.last == tl + depth << tl + atts = pba( atts ) + atts = shelve( atts ) if atts + lines[line_id] = "\t<#{ lT(tl) }l#{ atts }>\n\t
  • #{ content }" + else + lines[line_id] = "\t\t
  • #{ content }" + end + last_line = line_id - CODE_RE = /(\W) + else + last_line = line_id + end + if line_id - last_line > 1 or line_id == lines.length - 1 + while v = depth.pop + lines[last_line] << "
  • \n\t" + end + end + end + lines.join( "\n" ) + end + end + + QUOTES_RE = /(^>+([^\n]*?)(\n|$))+/m + QUOTES_CONTENT_RE = /^([> ]+)(.*)$/m + + def block_textile_quotes( text ) + text.gsub!( QUOTES_RE ) do |match| + lines = match.split( /\n/ ) + quotes = '' + indent = 0 + lines.each do |line| + line =~ QUOTES_CONTENT_RE + bq,content = $1, $2 + l = bq.count('>') + if l != indent + quotes << ("\n\n" + (l>indent ? '
    ' * (l-indent) : '
    ' * (indent-l)) + "\n\n") + indent = l + end + quotes << (content + "\n") + end + quotes << ("\n" + '' * indent + "\n\n") + quotes + end + end + + CODE_RE = /(\W) @ (?:\|(\w+?)\|)? (.+?) @ (?=\W)/x - def inline_textile_code( text ) - text.gsub!( CODE_RE ) do |m| - before,lang,code,after = $~[1..4] - lang = " lang=\"#{ lang }\"" if lang - rip_offtags( "#{ before }#{ code }#{ after }", false ) - end + def inline_textile_code( text ) + text.gsub!( CODE_RE ) do |m| + before,lang,code,after = $~[1..4] + lang = " lang=\"#{ lang }\"" if lang + rip_offtags( "#{ before }#{ code }#{ after }", false ) end + end - def lT( text ) - text =~ /\#$/ ? 'o' : 'u' - end + def lT( text ) + text =~ /\#$/ ? 'o' : 'u' + end - def hard_break( text ) - text.gsub!( /(.)\n(?!\Z| *([#*=]+(\s|$)|[{|]))/, "\\1
    " ) if hard_breaks - end + def hard_break( text ) + text.gsub!( /(.)\n(?!\Z| *([#*=]+(\s|$)|[{|]))/, "\\1
    " ) if hard_breaks + end - BLOCKS_GROUP_RE = /\n{2,}(?! )/m + BLOCKS_GROUP_RE = /\n{2,}(?! )/m - def blocks( text, deep_code = false ) - text.replace( text.split( BLOCKS_GROUP_RE ).collect do |blk| - plain = blk !~ /\A[#*> ]/ + def blocks( text, deep_code = false ) + text.replace( text.split( BLOCKS_GROUP_RE ).collect do |blk| + plain = blk !~ /\A[#*> ]/ - # skip blocks that are complex HTML - if blk =~ /^<\/?(\w+).*>/ and not SIMPLE_HTML_TAGS.include? $1 - blk + # skip blocks that are complex HTML + if blk =~ /^<\/?(\w+).*>/ and not SIMPLE_HTML_TAGS.include? $1 + blk + else + # search for indentation levels + blk.strip! + if blk.empty? + blk + else + code_blk = nil + blk.gsub!( /((?:\n(?:\n^ +[^\n]*)+)+)/m ) do |iblk| + flush_left iblk + blocks iblk, plain + iblk.gsub( /^(\S)/, "\t\\1" ) + if plain + code_blk = iblk; "" else - # search for indentation levels - blk.strip! - if blk.empty? - blk - else - code_blk = nil - blk.gsub!( /((?:\n(?:\n^ +[^\n]*)+)+)/m ) do |iblk| - flush_left iblk - blocks iblk, plain - iblk.gsub( /^(\S)/, "\t\\1" ) - if plain - code_blk = iblk; "" - else - iblk - end - end - - block_applied = 0 - @rules.each do |rule_name| - block_applied += 1 if ( rule_name.to_s.match /^block_/ and method( rule_name ).call( blk ) ) - end - if block_applied.zero? - if deep_code - blk = "\t
    #{ blk }
    " - else - blk = "\t

    #{ blk }

    " - end - end - # hard_break blk - blk + "\n#{ code_blk }" - end + iblk end + end - end.join( "\n\n" ) ) - end - - def textile_bq( tag, atts, cite, content ) - cite, cite_title = check_refs( cite ) - cite = " cite=\"#{ cite }\"" if cite - atts = shelve( atts ) if atts - "\t\n\t\t#{ content }

    \n\t" - end - - def textile_p( tag, atts, cite, content ) - atts = shelve( atts ) if atts - "\t<#{ tag }#{ atts }>#{ content }" - end - - alias textile_h1 textile_p - alias textile_h3 textile_p - alias textile_h3 textile_p - alias textile_h4 textile_p - alias textile_h5 textile_p - alias textile_h6 textile_p - - def textile_fn_( tag, num, atts, cite, content ) - atts << " id=\"fn#{ num }\" class=\"footnote\"" - content = "#{ num } #{ content }" - atts = shelve( atts ) if atts - "\t#{ content }

    " - end - - BLOCK_RE = /^(([a-z]+)(\d*))(#{A}#{C})\.(?::(\S+))? (.*)$/m - - def block_textile_prefix( text ) - if text =~ BLOCK_RE - tag,tagpre,num,atts,cite,content = $~[1..6] - atts = pba( atts ) - - # pass to prefix handler - replacement = nil - if respond_to? "textile_#{ tag }", true - replacement = method( "textile_#{ tag }" ).call( tag, atts, cite, content ) - elsif respond_to? "textile_#{ tagpre }_", true - replacement = method( "textile_#{ tagpre }_" ).call( tagpre, num, atts, cite, content ) + block_applied = 0 + @rules.each do |rule_name| + block_applied += 1 if ( rule_name.to_s.match /^block_/ and method( rule_name ).call( blk ) ) + end + if block_applied.zero? + if deep_code + blk = "\t
    #{ blk }
    " + else + blk = "\t

    #{ blk }

    " end - text.gsub!( $& ) { replacement } if replacement + end + # hard_break blk + blk + "\n#{ code_blk }" end - end - - SETEXT_RE = /\A(.+?)\n([=-])[=-]* *$/m - def block_markdown_setext( text ) - if text =~ SETEXT_RE - tag = if $2 == "="; "h1"; else; "h3"; end - blk, cont = "<#{ tag }>#{ $1 }", $' - blocks cont - text.replace( blk + cont ) - end - end + end - ATX_RE = /\A(\#{1,6}) # $1 = string of #'s + end.join( "\n\n" ) ) + end + + def textile_bq( tag, atts, cite, content ) + cite, cite_title = check_refs( cite ) + cite = " cite=\"#{ cite }\"" if cite + atts = shelve( atts ) if atts + "\t\n\t\t#{ content }

    \n\t" + end + + def textile_p( tag, atts, cite, content ) + atts = shelve( atts ) if atts + "\t<#{ tag }#{ atts }>#{ content }" + end + + alias textile_h1 textile_p + alias textile_h2 textile_p + alias textile_h3 textile_p + alias textile_h4 textile_p + alias textile_h5 textile_p + alias textile_h6 textile_p + + def textile_fn_( tag, num, atts, cite, content ) + atts << " id=\"fn#{ num }\" class=\"footnote\"" + content = "#{ num } #{ content }" + atts = shelve( atts ) if atts + "\t#{ content }

    " + end + + BLOCK_RE = /^(([a-z]+)(\d*))(#{A}#{C})\.(?::(\S+))? (.*)$/m + + def block_textile_prefix( text ) + if text =~ BLOCK_RE + tag,tagpre,num,atts,cite,content = $~[1..6] + atts = pba( atts ) + + # pass to prefix handler + replacement = nil + if respond_to? "textile_#{ tag }", true + replacement = method( "textile_#{ tag }" ).call( tag, atts, cite, content ) + elsif respond_to? "textile_#{ tagpre }_", true + replacement = method( "textile_#{ tagpre }_" ).call( tagpre, num, atts, cite, content ) + end + text.gsub!( $& ) { replacement } if replacement + end + end + + SETEXT_RE = /\A(.+?)\n([=-])[=-]* *$/m + def block_markdown_setext( text ) + if text =~ SETEXT_RE + tag = if $2 == "="; "h1"; else; "h2"; end + blk, cont = "<#{ tag }>#{ $1 }", $' + blocks cont + text.replace( blk + cont ) + end + end + + ATX_RE = /\A(\#{1,6}) # $1 = string of #'s [ ]* (.+?) # $2 = Header text [ ]* \#* # optional closing #'s (not counted) $/x - def block_markdown_atx( text ) - if text =~ ATX_RE - tag = "h#{ $1.length }" - blk, cont = "<#{ tag }>#{ $2 }\n\n", $' - blocks cont - text.replace( blk + cont ) - end + def block_markdown_atx( text ) + if text =~ ATX_RE + tag = "h#{ $1.length }" + blk, cont = "<#{ tag }>#{ $2 }\n\n", $' + blocks cont + text.replace( blk + cont ) end + end - MARKDOWN_BQ_RE = /\A(^ *> ?.+$(.+\n)*\n*)+/m + MARKDOWN_BQ_RE = /\A(^ *> ?.+$(.+\n)*\n*)+/m - def block_markdown_bq( text ) - text.gsub!( MARKDOWN_BQ_RE ) do |blk| - blk.gsub!( /^ *> ?/, '' ) - flush_left blk - blocks blk - blk.gsub!( /^(\S)/, "\t\\1" ) - "
    \n#{ blk }\n
    \n\n" - end + def block_markdown_bq( text ) + text.gsub!( MARKDOWN_BQ_RE ) do |blk| + blk.gsub!( /^ *> ?/, '' ) + flush_left blk + blocks blk + blk.gsub!( /^(\S)/, "\t\\1" ) + "
    \n#{ blk }\n
    \n\n" end + end - MARKDOWN_RULE_RE = /^(#{ - ['*', '-', '_'].collect { |ch| ' ?(' + Regexp::quote( ch ) + ' ?){3,}' }.join( '|' ) - })$/ + MARKDOWN_RULE_RE = /^(#{ + ['*', '-', '_'].collect { |ch| ' ?(' + Regexp::quote( ch ) + ' ?){3,}' }.join( '|' ) + })$/ - def block_markdown_rule( text ) - text.gsub!( MARKDOWN_RULE_RE ) do |blk| - "
    " - end + def block_markdown_rule( text ) + text.gsub!( MARKDOWN_RULE_RE ) do |blk| + "
    " end + end - # XXX TODO XXX - def block_markdown_lists( text ) - end + # XXX TODO XXX + def block_markdown_lists( text ) + end - def inline_textile_span( text ) - QTAGS.each do |qtag_rc, ht, qtag_re, rtype| - text.gsub!( qtag_re ) do |m| - - case rtype - when :limit - sta,oqs,qtag,content,oqa = $~[1..6] - atts = nil - if content =~ /^(#{C})(.+)$/ - atts, content = $~[1..2] - end - else - qtag,atts,cite,content = $~[1..4] - sta = '' - end - atts = pba( atts ) - atts = shelve( atts ) if atts - - "#{ sta }#{ oqs }<#{ ht }#{ atts }>#{ content }#{ oqa }" + def inline_textile_span( text ) + QTAGS.each do |qtag_rc, ht, qtag_re, rtype| + text.gsub!( qtag_re ) do |m| + case rtype + when :limit + sta,oqs,qtag,content,oqa = $~[1..6] + atts = nil + if content =~ /^(#{C})(.+)$/ + atts, content = $~[1..2] end + else + qtag,atts,cite,content = $~[1..4] + sta = '' end - end + atts = pba( atts ) + atts = shelve( atts ) if atts - LINK_RE = / + "#{ sta }#{ oqs }<#{ ht }#{ atts }>#{ content }#{ oqa }" + + end + end + end + + LINK_RE = / ( ([\s\[{(]|[#{PUNCT}])? # $pre " # start @@ -822,61 +822,61 @@ class RedCloth3 < String ([^[:alnum:]_\=\/;\(\)]*?) # $post ) (?=<|\s|$) - /x -#" - def inline_textile_link( text ) - text.gsub!( LINK_RE ) do |m| - all,pre,atts,text,title,url,proto,slash,post = $~[1..9] - if text.include?('
    ') - all - else - url, url_title = check_refs( url ) - title ||= url_title - - # Idea below : an URL with unbalanced parethesis and - # ending by ')' is put into external parenthesis - if ( url[-1]==?) and ((url.count("(") - url.count(")")) < 0 ) ) - url=url[0..-2] # discard closing parenth from url - post = ")"+post # add closing parenth to post - end - atts = pba( atts ) - atts = " href=\"#{ htmlesc url }#{ slash }\"#{ atts }" - atts << " title=\"#{ htmlesc title }\"" if title - atts = shelve( atts ) if atts - - external = (url =~ /^https?:\/\//) ? ' class="external"' : '' - - "#{ pre }#{ text }#{ post }" - end - end - end + /x + #" + def inline_textile_link( text ) + text.gsub!( LINK_RE ) do |m| + all,pre,atts,text,title,url,proto,slash,post = $~[1..9] + if text.include?('
    ') + all + else + url, url_title = check_refs( url ) + title ||= url_title - MARKDOWN_REFLINK_RE = / + # Idea below : an URL with unbalanced parethesis and + # ending by ')' is put into external parenthesis + if ( url[-1]==?) and ((url.count("(") - url.count(")")) < 0 ) ) + url=url[0..-2] # discard closing parenth from url + post = ")"+post # add closing parenth to post + end + atts = pba( atts ) + atts = " href=\"#{ htmlesc url }#{ slash }\"#{ atts }" + atts << " title=\"#{ htmlesc title }\"" if title + atts = shelve( atts ) if atts + + external = (url =~ /^https?:\/\//) ? ' class="external"' : '' + + "#{ pre }#{ text }#{ post }" + end + end + end + + MARKDOWN_REFLINK_RE = / \[([^\[\]]+)\] # $text [ ]? # opt. space (?:\n[ ]*)? # one optional newline followed by spaces \[(.*?)\] # $id - /x + /x - def inline_markdown_reflink( text ) - text.gsub!( MARKDOWN_REFLINK_RE ) do |m| - text, id = $~[1..2] + def inline_markdown_reflink( text ) + text.gsub!( MARKDOWN_REFLINK_RE ) do |m| + text, id = $~[1..2] - if id.empty? - url, title = check_refs( text ) - else - url, title = check_refs( id ) - end - - atts = " href=\"#{ url }\"" - atts << " title=\"#{ title }\"" if title - atts = shelve( atts ) - - "#{ text }" - end + if id.empty? + url, title = check_refs( text ) + else + url, title = check_refs( id ) + end + + atts = " href=\"#{ url }\"" + atts << " title=\"#{ title }\"" if title + atts = shelve( atts ) + + "#{ text }" end + end - MARKDOWN_LINK_RE = / + MARKDOWN_LINK_RE = / \[([^\[\]]+)\] # $text \( # open paren [ \t]* # opt space @@ -888,52 +888,52 @@ class RedCloth3 < String \3 # matching quote )? # title is optional \) - /x + /x - def inline_markdown_link( text ) - text.gsub!( MARKDOWN_LINK_RE ) do |m| - text, url, quote, title = $~[1..4] + def inline_markdown_link( text ) + text.gsub!( MARKDOWN_LINK_RE ) do |m| + text, url, quote, title = $~[1..4] - atts = " href=\"#{ url }\"" - atts << " title=\"#{ title }\"" if title - atts = shelve( atts ) - - "#{ text }" - end + atts = " href=\"#{ url }\"" + atts << " title=\"#{ title }\"" if title + atts = shelve( atts ) + + "#{ text }" end + end - TEXTILE_REFS_RE = /(^ *)\[([^\[\n]+?)\](#{HYPERLINK})(?=\s|$)/ - MARKDOWN_REFS_RE = /(^ *)\[([^\n]+?)\]:\s+?(?:\s+"((?:[^"]|\\")+)")?(?=\s|$)/m + TEXTILE_REFS_RE = /(^ *)\[([^\[\n]+?)\](#{HYPERLINK})(?=\s|$)/ + MARKDOWN_REFS_RE = /(^ *)\[([^\n]+?)\]:\s+?(?:\s+"((?:[^"]|\\")+)")?(?=\s|$)/m - def refs( text ) - @rules.each do |rule_name| - method( rule_name ).call( text ) if rule_name.to_s.match /^refs_/ - end + def refs( text ) + @rules.each do |rule_name| + method( rule_name ).call( text ) if rule_name.to_s.match /^refs_/ end + end - def refs_textile( text ) - text.gsub!( TEXTILE_REFS_RE ) do |m| - flag, url = $~[2..3] - @urlrefs[flag.downcase] = [url, nil] - nil - end - end - - def refs_markdown( text ) - text.gsub!( MARKDOWN_REFS_RE ) do |m| - flag, url = $~[2..3] - title = $~[6] - @urlrefs[flag.downcase] = [url, title] - nil - end + def refs_textile( text ) + text.gsub!( TEXTILE_REFS_RE ) do |m| + flag, url = $~[2..3] + @urlrefs[flag.downcase] = [url, nil] + nil end + end - def check_refs( text ) - ret = @urlrefs[text.downcase] if text - ret || [text, nil] + def refs_markdown( text ) + text.gsub!( MARKDOWN_REFS_RE ) do |m| + flag, url = $~[2..3] + title = $~[6] + @urlrefs[flag.downcase] = [url, title] + nil end + end - IMAGE_RE = / + def check_refs( text ) + ret = @urlrefs[text.downcase] if text + ret || [text, nil] + end + + IMAGE_RE = / (>|\s|^) # start of line? \! # opening (\<|\=|\>)? # optional alignment atts @@ -944,265 +944,265 @@ class RedCloth3 < String (?:\(((?:[^\(\)]|\([^\)]+\))+?)\))? # optional title \! # closing (?::#{ HYPERLINK })? # optional href - /x + /x - def inline_textile_image( text ) - text.gsub!( IMAGE_RE ) do |m| - stln,algn,atts,url,title,href,href_a1,href_a2 = $~[1..8] - htmlesc title - atts = pba( atts ) - atts = " src=\"#{ htmlesc url.dup }\"#{ atts }" - atts << " title=\"#{ title }\"" if title - atts << " alt=\"#{ title }\"" - # size = @getimagesize($url); - # if($size) $atts.= " $size[3]"; + def inline_textile_image( text ) + text.gsub!( IMAGE_RE ) do |m| + stln,algn,atts,url,title,href,href_a1,href_a2 = $~[1..8] + htmlesc title + atts = pba( atts ) + atts = " src=\"#{ htmlesc url.dup }\"#{ atts }" + atts << " title=\"#{ title }\"" if title + atts << " alt=\"#{ title }\"" + # size = @getimagesize($url); + # if($size) $atts.= " $size[3]"; - href, alt_title = check_refs( href ) if href - url, url_title = check_refs( url ) + href, alt_title = check_refs( href ) if href + url, url_title = check_refs( url ) - out = '' - out << "" if href - out << "" - out << "#{ href_a1 }#{ href_a2 }" if href - - if algn - algn = h_align( algn ) - if stln == "

    " - out = "

    #{ out }" - else - out = "#{ stln }

    #{ out }
    " - end - else - out = stln + out - end + out = '' + out << "" if href + out << "" + out << "#{ href_a1 }#{ href_a2 }" if href - out - end - end - - def shelve( val ) - @shelf << val - " :redsh##{ @shelf.length }:" - end - - def retrieve( text ) - @shelf.each_with_index do |r, i| - text.gsub!( " :redsh##{ i + 1 }:", r ) - end - end - - def incoming_entities( text ) - ## turn any incoming ampersands into a dummy character for now. - ## This uses a negative lookahead for alphanumerics followed by a semicolon, - ## implying an incoming html entity, to be skipped - - text.gsub!( /&(?![#a-z0-9]+;)/i, "x%x%" ) - end - - def no_textile( text ) - text.gsub!( /(^|\s)==([^=]+.*?)==(\s|$)?/, - '\1\2\3' ) - text.gsub!( /^ *==([^=]+.*?)==/m, - '\1\2\3' ) - end - - def clean_white_space( text ) - # normalize line breaks - text.gsub!( /\r\n/, "\n" ) - text.gsub!( /\r/, "\n" ) - text.gsub!( /\t/, ' ' ) - text.gsub!( /^ +$/, '' ) - text.gsub!( /\n{3,}/, "\n\n" ) - text.gsub!( /"$/, "\" " ) - - # if entire document is indented, flush - # to the left side - flush_left text - end - - def flush_left( text ) - indt = 0 - if text =~ /^ / - while text !~ /^ {#{indt}}\S/ - indt += 1 - end unless text.empty? - if indt.nonzero? - text.gsub!( /^ {#{indt}}/, '' ) - end - end - end - - def footnote_ref( text ) - text.gsub!( /\b\[([0-9]+?)\](\s)?/, - '\1\2' ) - end - - OFFTAGS = /(code|pre|kbd|notextile)/ - OFFTAG_MATCH = /(?:(<\/#{ OFFTAGS }>)|(<#{ OFFTAGS }[^>]*>))(.*?)(?=<\/?#{ OFFTAGS }\W|\Z)/mi - OFFTAG_OPEN = /<#{ OFFTAGS }/ - OFFTAG_CLOSE = /<\/?#{ OFFTAGS }/ - HASTAG_MATCH = /(<\/?\w[^\n]*?>)/m - ALLTAG_MATCH = /(<\/?\w[^\n]*?>)|.*?(?=<\/?\w[^\n]*?>|$)/m - - def glyphs_textile( text, level = 0 ) - if text !~ HASTAG_MATCH - pgl text - footnote_ref text + if algn + algn = h_align( algn ) + if stln == "

    " + out = "

    #{ out }" else - codepre = 0 - text.gsub!( ALLTAG_MATCH ) do |line| - ## matches are off if we're between ,

     etc.
    -                if $1
    -                    if line =~ OFFTAG_OPEN
    -                        codepre += 1
    -                    elsif line =~ OFFTAG_CLOSE
    -                        codepre -= 1
    -                        codepre = 0 if codepre < 0
    -                    end 
    -                elsif codepre.zero?
    -                    glyphs_textile( line, level + 1 )
    -                else
    -                    htmlesc( line, :NoQuotes )
    -                end
    -                # p [level, codepre, line]
    +          out = "#{ stln }
    #{ out }
    " + end + else + out = stln + out + end - line + out + end + end + + def shelve( val ) + @shelf << val + " :redsh##{ @shelf.length }:" + end + + def retrieve( text ) + @shelf.each_with_index do |r, i| + text.gsub!( " :redsh##{ i + 1 }:", r ) + end + end + + def incoming_entities( text ) + ## turn any incoming ampersands into a dummy character for now. + ## This uses a negative lookahead for alphanumerics followed by a semicolon, + ## implying an incoming html entity, to be skipped + + text.gsub!( /&(?![#a-z0-9]+;)/i, "x%x%" ) + end + + def no_textile( text ) + text.gsub!( /(^|\s)==([^=]+.*?)==(\s|$)?/, + '\1\2\3' ) + text.gsub!( /^ *==([^=]+.*?)==/m, + '\1\2\3' ) + end + + def clean_white_space( text ) + # normalize line breaks + text.gsub!( /\r\n/, "\n" ) + text.gsub!( /\r/, "\n" ) + text.gsub!( /\t/, ' ' ) + text.gsub!( /^ +$/, '' ) + text.gsub!( /\n{3,}/, "\n\n" ) + text.gsub!( /"$/, "\" " ) + + # if entire document is indented, flush + # to the left side + flush_left text + end + + def flush_left( text ) + indt = 0 + if text =~ /^ / + while text !~ /^ {#{indt}}\S/ + indt += 1 + end unless text.empty? + if indt.nonzero? + text.gsub!( /^ {#{indt}}/, '' ) + end + end + end + + def footnote_ref( text ) + text.gsub!( /\b\[([0-9]+?)\](\s)?/, + '\1\2' ) + end + + OFFTAGS = /(code|pre|kbd|notextile)/ + OFFTAG_MATCH = /(?:(<\/#{ OFFTAGS }>)|(<#{ OFFTAGS }[^>]*>))(.*?)(?=<\/?#{ OFFTAGS }\W|\Z)/mi + OFFTAG_OPEN = /<#{ OFFTAGS }/ + OFFTAG_CLOSE = /<\/?#{ OFFTAGS }/ + HASTAG_MATCH = /(<\/?\w[^\n]*?>)/m + ALLTAG_MATCH = /(<\/?\w[^\n]*?>)|.*?(?=<\/?\w[^\n]*?>|$)/m + + def glyphs_textile( text, level = 0 ) + if text !~ HASTAG_MATCH + pgl text + footnote_ref text + else + codepre = 0 + text.gsub!( ALLTAG_MATCH ) do |line| + ## matches are off if we're between ,
     etc.
    +        if $1
    +          if line =~ OFFTAG_OPEN
    +            codepre += 1
    +          elsif line =~ OFFTAG_CLOSE
    +            codepre -= 1
    +            codepre = 0 if codepre < 0
    +          end
    +        elsif codepre.zero?
    +          glyphs_textile( line, level + 1 )
    +        else
    +          htmlesc( line, :NoQuotes )
    +        end
    +        # p [level, codepre, line]
    +
    +        line
    +      end
    +    end
    +  end
    +
    +  def rip_offtags( text, escape_aftertag=true, escape_line=true )
    +    if text =~ /<.*>/
    +      ## strip and encode 
     content
    +      codepre, used_offtags = 0, {}
    +      text.gsub!( OFFTAG_MATCH ) do |line|
    +        if $3
    +          first, offtag, aftertag = $3, $4, $5
    +          codepre += 1
    +          used_offtags[offtag] = true
    +          if codepre - used_offtags.length > 0
    +            htmlesc( line, :NoQuotes ) if escape_line
    +            @pre_list.last << line
    +            line = ""
    +          else
    +            ### htmlesc is disabled between CODE tags which will be parsed with highlighter
    +            ### Regexp in formatter.rb is : /\s?(.+)/m
    +            ### NB: some changes were made not to use $N variables, because we use "match"
    +            ###   and it breaks following lines
    +            htmlesc( aftertag, :NoQuotes ) if aftertag && escape_aftertag && !first.match(//)
    +            line = ""
    +            first.match(/<#{ OFFTAGS }([^>]*)>/)
    +            tag = $1
    +            $2.to_s.match(/(class\=("[^"]+"|'[^']+'))/i)
    +            tag << " #{$1}" if $1
    +            @pre_list << "<#{ tag }>#{ aftertag }"
    +          end
    +        elsif $1 and codepre > 0
    +          if codepre - used_offtags.length > 0
    +            htmlesc( line, :NoQuotes ) if escape_line
    +            @pre_list.last << line
    +            line = ""
    +          end
    +          codepre -= 1 unless codepre.zero?
    +          used_offtags = {} if codepre.zero?
    +        end
    +        line
    +      end
    +    end
    +    text
    +  end
    +
    +  def smooth_offtags( text )
    +    unless @pre_list.empty?
    +      ## replace 
     content
    +      text.gsub!( // ) { @pre_list[$1.to_i] }
    +    end
    +  end
    +
    +  def inline( text )
    +    [/^inline_/, /^glyphs_/].each do |meth_re|
    +      @rules.each do |rule_name|
    +        method( rule_name ).call( text ) if rule_name.to_s.match( meth_re )
    +      end
    +    end
    +  end
    +
    +  def h_align( text )
    +    H_ALGN_VALS[text]
    +  end
    +
    +  def v_align( text )
    +    V_ALGN_VALS[text]
    +  end
    +
    +  def textile_popup_help( name, windowW, windowH )
    +    ' ' + name + '
    ' + end + + # HTML cleansing stuff + BASIC_TAGS = { + 'a' => ['href', 'title'], + 'img' => ['src', 'alt', 'title'], + 'br' => [], + 'i' => nil, + 'u' => nil, + 'b' => nil, + 'pre' => nil, + 'kbd' => nil, + 'code' => ['lang'], + 'cite' => nil, + 'strong' => nil, + 'em' => nil, + 'ins' => nil, + 'sup' => nil, + 'sub' => nil, + 'del' => nil, + 'table' => nil, + 'tr' => nil, + 'td' => ['colspan', 'rowspan'], + 'th' => nil, + 'ol' => nil, + 'ul' => nil, + 'li' => nil, + 'p' => nil, + 'h1' => nil, + 'h2' => nil, + 'h3' => nil, + 'h4' => nil, + 'h5' => nil, + 'h6' => nil, + 'blockquote' => ['cite'] + } + + def clean_html( text, tags = BASIC_TAGS ) + text.gsub!( /]*)>/ ) do + raw = $~ + tag = raw[2].downcase + if tags.has_key? tag + pcs = [tag] + tags[tag].each do |prop| + ['"', "'", ''].each do |q| + q2 = ( q != '' ? q : '\s' ) + if raw[3] =~ /#{prop}\s*=\s*#{q}([^#{q2}]+)#{q}/i + attrv = $1 + next if prop == 'src' and attrv =~ %r{^(?!http)\w+:} + pcs << "#{prop}=\"#{$1.gsub('"', '\\"')}\"" + break end - end + end + end if tags[tag] + "<#{raw[1]}#{pcs.join " "}>" + else + " " + end end + end - def rip_offtags( text, escape_aftertag=true, escape_line=true ) - if text =~ /<.*>/ - ## strip and encode
     content
    -            codepre, used_offtags = 0, {}
    -            text.gsub!( OFFTAG_MATCH ) do |line|
    -                if $3
    -                    first, offtag, aftertag = $3, $4, $5
    -                    codepre += 1
    -                    used_offtags[offtag] = true
    -                    if codepre - used_offtags.length > 0
    -                        htmlesc( line, :NoQuotes ) if escape_line
    -                        @pre_list.last << line
    -                        line = ""
    -                    else
    -                        ### htmlesc is disabled between CODE tags which will be parsed with highlighter
    -                        ### Regexp in formatter.rb is : /\s?(.+)/m
    -                        ### NB: some changes were made not to use $N variables, because we use "match"
    -                        ###   and it breaks following lines
    -                        htmlesc( aftertag, :NoQuotes ) if aftertag && escape_aftertag && !first.match(//)
    -                        line = ""
    -                        first.match(/<#{ OFFTAGS }([^>]*)>/)
    -                        tag = $1
    -                        $2.to_s.match(/(class\=("[^"]+"|'[^']+'))/i)
    -                        tag << " #{$1}" if $1
    -                        @pre_list << "<#{ tag }>#{ aftertag }"
    -                    end
    -                elsif $1 and codepre > 0
    -                    if codepre - used_offtags.length > 0
    -                        htmlesc( line, :NoQuotes ) if escape_line
    -                        @pre_list.last << line
    -                        line = ""
    -                    end
    -                    codepre -= 1 unless codepre.zero?
    -                    used_offtags = {} if codepre.zero?
    -                end 
    -                line
    -            end
    -        end
    -        text
    -    end
    +  ALLOWED_TAGS = %w(redpre pre code notextile)
     
    -    def smooth_offtags( text )
    -        unless @pre_list.empty?
    -            ## replace 
     content
    -            text.gsub!( // ) { @pre_list[$1.to_i] }
    -        end
    -    end
    -
    -    def inline( text ) 
    -        [/^inline_/, /^glyphs_/].each do |meth_re|
    -            @rules.each do |rule_name|
    -                method( rule_name ).call( text ) if rule_name.to_s.match( meth_re )
    -            end
    -        end
    -    end
    -
    -    def h_align( text ) 
    -        H_ALGN_VALS[text]
    -    end
    -
    -    def v_align( text ) 
    -        V_ALGN_VALS[text]
    -    end
    -
    -    def textile_popup_help( name, windowW, windowH )
    -        ' ' + name + '
    ' - end - - # HTML cleansing stuff - BASIC_TAGS = { - 'a' => ['href', 'title'], - 'img' => ['src', 'alt', 'title'], - 'br' => [], - 'i' => nil, - 'u' => nil, - 'b' => nil, - 'pre' => nil, - 'kbd' => nil, - 'code' => ['lang'], - 'cite' => nil, - 'strong' => nil, - 'em' => nil, - 'ins' => nil, - 'sup' => nil, - 'sub' => nil, - 'del' => nil, - 'table' => nil, - 'tr' => nil, - 'td' => ['colspan', 'rowspan'], - 'th' => nil, - 'ol' => nil, - 'ul' => nil, - 'li' => nil, - 'p' => nil, - 'h1' => nil, - 'h3' => nil, - 'h3' => nil, - 'h4' => nil, - 'h5' => nil, - 'h6' => nil, - 'blockquote' => ['cite'] - } - - def clean_html( text, tags = BASIC_TAGS ) - text.gsub!( /]*)>/ ) do - raw = $~ - tag = raw[2].downcase - if tags.has_key? tag - pcs = [tag] - tags[tag].each do |prop| - ['"', "'", ''].each do |q| - q2 = ( q != '' ? q : '\s' ) - if raw[3] =~ /#{prop}\s*=\s*#{q}([^#{q2}]+)#{q}/i - attrv = $1 - next if prop == 'src' and attrv =~ %r{^(?!http)\w+:} - pcs << "#{prop}=\"#{$1.gsub('"', '\\"')}\"" - break - end - end - end if tags[tag] - "<#{raw[1]}#{pcs.join " "}>" - else - " " - end - end - end - - ALLOWED_TAGS = %w(redpre pre code notextile) - - def escape_html_tags(text) - text.gsub!(%r{<(\/?([!\w]+)[^<>\n]*)(>?)}) {|m| ALLOWED_TAGS.include?($2) ? "<#{$1}#{$3}" : "<#{$1}#{'>' unless $3.blank?}" } - end + def escape_html_tags(text) + text.gsub!(%r{<(\/?([!\w]+)[^<>\n]*)(>?)}) {|m| ALLOWED_TAGS.include?($2) ? "<#{$1}#{$3}" : "<#{$1}#{'>' unless $3.blank?}" } + end end diff --git a/public/application.css b/public/application.css deleted file mode 100644 index deb7b321..00000000 --- a/public/application.css +++ /dev/null @@ -1,1148 +0,0 @@ -html {overflow-y:scroll;} -body { font-family: Verdana, sans-serif; font-size: 12px; color:#484848; margin: 0; padding: 0; min-width: 900px; } - -h1, h2, h3, h4 {font-family: "Trebuchet MS", Verdana, sans-serif;padding: 2px 10px 1px 0px;margin: 0 0 10px 0;} -#content h1, h2, h3, h4 {color: #555;} -h2, .wiki h1 {font-size: 20px;} -h3, .wiki h2 {font-size: 16px;} -h4, .wiki h3 {font-size: 13px;} -h4 {border-bottom: 1px dotted #bbb;} - -/***** Layout *****/ -#wrapper {background: white;} - -#top-menu {background: #3E5B76; color: #000; height:1.8em; font-size: 1.0em; padding: 2px 2px 0px 6px;} -#top-menu ul {margin: 0; padding: 0;} -#top-menu li { - float:left; - list-style-type:none; - margin: 0px 0px 0px 0px; - padding: 0px 0px 0px 0px; - white-space:nowrap; -} -#top-menu a {color: #000000; margin-right: 8px; font-weight: bold;} -#top-menu #loggedas { float: right; margin-right: 0.5em; color: #fff; } - -#account {float:right;} - -#header {min-height:5.3em;margin:0;background-color:#628DB6;color:#f8f8f8; padding: 4px 8px 20px 6px; position:relative;} -#header a {color:#f8f8f8;} -#header h1 a.ancestor { font-size: 80%; } -#quick-search {float:right;} - -#main-menu {position: absolute; bottom: 0px; left:6px; margin-right: -500px;} -#main-menu ul {margin: 0; padding: 0;} -#main-menu li { - float:left; - list-style-type:none; - margin: 0px 2px 0px 0px; - padding: 0px 0px 0px 0px; - white-space:nowrap; -} -#main-menu li a { - display: block; - color: #039ea0; - text-decoration: none; - font-weight: bold; - margin: 0; - padding: 4px 10px 4px 10px; -} -#main-menu li a:hover {background:#759FCF; color:#fff;} -#main-menu li a.selected, #main-menu li a.selected:hover {background:#fff; color:#555;} - -#admin-menu ul {margin: 0; padding: 0;} -#admin-menu li {margin: 0; padding: 0 0 6px 0; list-style-type:none;} - -#admin-menu a { background-position: 0% 40%; background-repeat: no-repeat; padding-left: 20px; padding-top: 2px; padding-bottom: 3px;} -#admin-menu a.projects { background-image: url(../images/projects.png); } -#admin-menu a.users { background-image: url(../images/user.png); } -#admin-menu a.groups { background-image: url(../images/group.png); } -#admin-menu a.roles { background-image: url(../images/database_key.png); } -#admin-menu a.trackers { background-image: url(../images/ticket.png); } -#admin-menu a.issue_statuses { background-image: url(../images/ticket_edit.png); } -#admin-menu a.workflows { background-image: url(../images/ticket_go.png); } -#admin-menu a.custom_fields { background-image: url(../images/textfield.png); } -#admin-menu a.enumerations { background-image: url(../images/text_list_bullets.png); } -#admin-menu a.settings { background-image: url(../images/changeset.png); } -#admin-menu a.plugins { background-image: url(../images/plugin.png); } -#admin-menu a.info { background-image: url(../images/help.png); } -#admin-menu a.server_authentication { background-image: url(../images/server_key.png); } - -#main {background-color:#EEEEEE;} - -#sidebar{ float: right; width: 22%; position: relative; z-index: 9; padding: 0; margin: 0;} -* html #sidebar{ width: 22%; } -#sidebar h3{ font-size: 14px; margin-top:14px; color: #666; } -#sidebar hr{ width: 100%; margin: 0 auto; height: 1px; background: #ccc; border: 0; } -* html #sidebar hr{ width: 95%; position: relative; left: -6px; color: #ccc; } -#sidebar .contextual { margin-right: 1em; } - -#content { width: 75%; background-color: #fff; margin: 0px; border-right: 1px solid #ddd; padding: 6px 10px 10px 10px; z-index: 10; } -* html #content{ width: 75%; padding-left: 0; margin-top: 0px; padding: 6px 10px 10px 10px;} -html>body #content { min-height: 600px; } -* html body #content { height: 600px; } /* IE */ - -#main.nosidebar #sidebar{ display: none; } -#main.nosidebar #content{ width: auto; border-right: 0; } - -#footer {clear: both; border-top: 1px solid #bbb; font-size: 0.9em; color: #aaa; padding: 5px; text-align:center; background:#fff;} - -#login-form table {margin-top:5em; padding:1em; margin-left: auto; margin-right: auto; border: 2px solid #FDBF3B; background-color:#FFEBC1; } -#login-form table td {padding: 6px;} -#login-form label {font-weight: bold;} -#login-form input#username, #login-form input#password { width: 300px; } - -div.modal { border-radius:5px; background:#fff; z-index:50; padding:4px;} -div.modal h3.title {display:none;} -div.modal p.buttons {text-align:right; margin-bottom:0;} - -input#openid_url { background: url(../images/openid-bg.gif) no-repeat; background-color: #fff; background-position: 0 50%; padding-left: 18px; } - -.clear:after{ content: "."; display: block; height: 0; clear: both; visibility: hidden; } - -/***** Links *****/ -a, a:link, a:visited{ color: #169; text-decoration: none; } -a:hover, a:active{ color: #c61a1a; text-decoration: underline;} -a img{ border: 0; } - -a.issue.closed, a.issue.closed:link, a.issue.closed:visited { color: #999; text-decoration: line-through; } -a.project.closed, a.project.closed:link, a.project.closed:visited { color: #999; } -a.user.locked, a.user.locked:link, a.user.locked:visited {color: #999;} - -#sidebar a.selected {line-height:1.7em; padding:1px 3px 2px 2px; margin-left:-2px; background-color:#9DB9D5; color:#fff; border-radius:2px;} -#sidebar a.selected:hover {text-decoration:none;} -#admin-menu a {line-height:1.7em;} -#admin-menu a.selected {padding-left: 20px !important; background-position: 2px 40%;} - -a.collapsible {padding-left: 12px; background: url(../images/arrow_expanded.png) no-repeat -3px 40%;} -a.collapsible.collapsed {background: url(../images/arrow_collapsed.png) no-repeat -5px 40%;} - -a#toggle-completed-versions {color:#999;} -/***** Tables *****/ -table.list { border: 1px solid #e4e4e4; border-collapse: collapse; width: 100%; margin-bottom: 4px; } -table.list th { background-color:#EEEEEE; padding: 4px; white-space:nowrap; } -table.list td { vertical-align: top; padding-right:10px; } -table.list td.id { width: 2%; text-align: center;} -table.list td.checkbox { width: 15px; padding: 2px 0 0 0; } -table.list td.checkbox input {padding:0px;} -table.list td.buttons { width: 15%; white-space:nowrap; text-align: right; } -table.list td.buttons a { padding-right: 0.6em; } -table.list caption { text-align: left; padding: 0.5em 0.5em 0.5em 0; } - -tr.project td.name a { white-space:nowrap; } -tr.project.closed, tr.project.archived { color: #aaa; } -tr.project.closed a, tr.project.archived a { color: #aaa; } - -tr.project.idnt td.name span {background: url(../images/bullet_arrow_right.png) no-repeat 0 50%; padding-left: 16px;} -tr.project.idnt-1 td.name {padding-left: 0.5em;} -tr.project.idnt-2 td.name {padding-left: 2em;} -tr.project.idnt-3 td.name {padding-left: 3.5em;} -tr.project.idnt-4 td.name {padding-left: 5em;} -tr.project.idnt-5 td.name {padding-left: 6.5em;} -tr.project.idnt-6 td.name {padding-left: 8em;} -tr.project.idnt-7 td.name {padding-left: 9.5em;} -tr.project.idnt-8 td.name {padding-left: 11em;} -tr.project.idnt-9 td.name {padding-left: 12.5em;} - -tr.issue { text-align: center; white-space: nowrap; } -tr.issue td.subject, tr.issue td.category, td.assigned_to, tr.issue td.string, tr.issue td.text, tr.issue td.relations { white-space: normal; } -tr.issue td.subject, tr.issue td.relations { text-align: left; } -tr.issue td.done_ratio table.progress { margin-left:auto; margin-right: auto;} -tr.issue td.relations span {white-space: nowrap;} -table.issues td.description {color:#777; font-size:90%; padding:4px 4px 4px 24px; text-align:left; white-space:normal;} -table.issues td.description pre {white-space:normal;} - -tr.issue.idnt td.subject a {background: url(../images/bullet_arrow_right.png) no-repeat 0 50%; padding-left: 16px;} -tr.issue.idnt-1 td.subject {padding-left: 0.5em;} -tr.issue.idnt-2 td.subject {padding-left: 2em;} -tr.issue.idnt-3 td.subject {padding-left: 3.5em;} -tr.issue.idnt-4 td.subject {padding-left: 5em;} -tr.issue.idnt-5 td.subject {padding-left: 6.5em;} -tr.issue.idnt-6 td.subject {padding-left: 8em;} -tr.issue.idnt-7 td.subject {padding-left: 9.5em;} -tr.issue.idnt-8 td.subject {padding-left: 11em;} -tr.issue.idnt-9 td.subject {padding-left: 12.5em;} - -tr.entry { border: 1px solid #f8f8f8; } -tr.entry td { white-space: nowrap; } -tr.entry td.filename { width: 30%; } -tr.entry td.filename_no_report { width: 70%; } -tr.entry td.size { text-align: right; font-size: 90%; } -tr.entry td.revision, tr.entry td.author { text-align: center; } -tr.entry td.age { text-align: right; } -tr.entry.file td.filename a { margin-left: 16px; } -tr.entry.file td.filename_no_report a { margin-left: 16px; } - -tr span.expander {background-image: url(../images/bullet_toggle_plus.png); padding-left: 8px; margin-left: 0; cursor: pointer;} -tr.open span.expander {background-image: url(../images/bullet_toggle_minus.png);} - -tr.changeset { height: 20px } -tr.changeset ul, ol { margin-top: 0px; margin-bottom: 0px; } -tr.changeset td.revision_graph { width: 15%; background-color: #fffffb; } -tr.changeset td.author { text-align: center; width: 15%; white-space:nowrap;} -tr.changeset td.committed_on { text-align: center; width: 15%; white-space:nowrap;} - -table.files tr.file td { text-align: center; } -table.files tr.file td.filename { text-align: left; padding-left: 24px; } -table.files tr.file td.digest { font-size: 80%; } - -table.members td.roles, table.memberships td.roles { width: 45%; } - -tr.message { height: 2.6em; } -tr.message td.subject { padding-left: 20px; } -tr.message td.created_on { white-space: nowrap; } -tr.message td.last_message { font-size: 80%; white-space: nowrap; } -tr.message.locked td.subject { background: url(../images/locked.png) no-repeat 0 1px; } -tr.message.sticky td.subject { background: url(../images/bullet_go.png) no-repeat 0 1px; font-weight: bold; } - -tr.version.closed, tr.version.closed a { color: #999; } -tr.version td.name { padding-left: 20px; } -tr.version.shared td.name { background: url(../images/link.png) no-repeat 0% 70%; } -tr.version td.date, tr.version td.status, tr.version td.sharing { text-align: center; white-space:nowrap; } - -tr.user td { width:13%; } -tr.user td.email { width:18%; } -tr.user td { white-space: nowrap; } -tr.user.locked, tr.user.registered { color: #aaa; } -tr.user.locked a, tr.user.registered a { color: #aaa; } - -table.permissions td.role {color:#999;font-size:90%;font-weight:normal !important;text-align:center;vertical-align:bottom;} - -tr.wiki-page-version td.updated_on, tr.wiki-page-version td.author {text-align:center;} - -tr.time-entry { text-align: center; white-space: nowrap; } -tr.time-entry td.issue, tr.time-entry td.comments { text-align: left; white-space: normal; } -td.hours { text-align: right; font-weight: bold; padding-right: 0.5em; } -td.hours .hours-dec { font-size: 0.9em; } - -table.plugins td { vertical-align: middle; } -table.plugins td.configure { text-align: right; padding-right: 1em; } -table.plugins span.name { font-weight: bold; display: block; margin-bottom: 6px; } -table.plugins span.description { display: block; font-size: 0.9em; } -table.plugins span.url { display: block; font-size: 0.9em; } - -table.list tbody tr.group td { padding: 0.8em 0 0.5em 0.3em; font-weight: bold; border-bottom: 1px solid #ccc; } -table.list tbody tr.group span.count {position:relative; top:-1px; color:#fff; font-size:10px; background:#9DB9D5; padding:0px 6px 1px 6px; border-radius:3px; margin-left:4px;} -tr.group a.toggle-all { color: #aaa; font-size: 80%; font-weight: normal; display:none;} -tr.group:hover a.toggle-all { display:inline;} -a.toggle-all:hover {text-decoration:none;} - -table.list tbody tr:hover { background-color:#ffffdd; } -table.list tbody tr.group:hover { background-color:inherit; } -table td {padding:2px;} -table p {margin:0;} -.odd {background-color:#f6f7f8;} -.even {background-color: #fff;} - -a.sort { padding-right: 16px; background-position: 100% 50%; background-repeat: no-repeat; } -a.sort.asc { background-image: url(../images/sort_asc.png); } -a.sort.desc { background-image: url(../images/sort_desc.png); } - -table.attributes { width: 100% } -table.attributes th { vertical-align: top; text-align: left; } -table.attributes td { vertical-align: top; } - -table.boards a.board, h3.comments { background: url(../images/comment.png) no-repeat 0% 50%; padding-left: 20px; } -table.boards td.topic-count, table.boards td.message-count {text-align:center;} -table.boards td.last-message {font-size:80%;} - -table.messages td.author, table.messages td.created_on, table.messages td.reply-count {text-align:center;} - -table.query-columns { - border-collapse: collapse; - border: 0; -} - -table.query-columns td.buttons { - vertical-align: middle; - text-align: center; -} - -td.center {text-align:center;} - -h3.version { background: url(../images/package.png) no-repeat 0% 50%; padding-left: 20px; } - -div.issues h3 { background: url(../images/ticket.png) no-repeat 0% 50%; padding-left: 20px; } -div.members h3 { background: url(../images/group.png) no-repeat 0% 50%; padding-left: 20px; } -div.news h3 { background: url(../images/news.png) no-repeat 0% 50%; padding-left: 20px; } -div.projects h3 { background: url(../images/projects.png) no-repeat 0% 50%; padding-left: 20px; } - -#watchers ul {margin: 0; padding: 0;} -#watchers li {list-style-type:none;margin: 0px 2px 0px 0px; padding: 0px 0px 0px 0px;} -#watchers select {width: 95%; display: block;} -#watchers a.delete {opacity: 0.4; vertical-align: middle;} -#watchers a.delete:hover {opacity: 1;} -#watchers img.gravatar {margin: 0 4px 2px 0;} - -span#watchers_inputs {overflow:auto; display:block;} -span.search_for_watchers {display:block;} -span.search_for_watchers, span.add_attachment {font-size:80%; line-height:2.5em;} -span.search_for_watchers a, span.add_attachment a {padding-left:16px; background: url(../images/bullet_add.png) no-repeat 0 50%; } - - -.highlight { background-color: #FCFD8D;} -.highlight.token-1 { background-color: #faa;} -.highlight.token-2 { background-color: #afa;} -.highlight.token-3 { background-color: #aaf;} - -.box{ - padding:6px; - margin-bottom: 10px; - background-color:#f6f6f6; - color:#505050; - line-height:1.5em; - border: 1px solid #e4e4e4; -} - -div.square { - border: 1px solid #999; - float: left; - margin: .3em .4em 0 .4em; - overflow: hidden; - width: .6em; height: .6em; -} -.contextual {float:right; white-space: nowrap; line-height:1.4em;margin-top:5px; padding-left: 10px; font-size:0.9em;} -.contextual input, .contextual select {font-size:0.9em;} -.message .contextual { margin-top: 0; } - -.splitcontent {overflow:auto;} -.splitcontentleft{float:left; width:49%;} -.splitcontentright{float:right; width:49%;} -form {display: inline;} -input, select {vertical-align: middle; margin-top: 1px; margin-bottom: 1px;} -fieldset {border: 1px solid #e4e4e4; margin:0;} -legend {color: #484848;} -hr { width: 100%; height: 1px; background: #ccc; border: 0;} -blockquote { font-style: italic; border-left: 3px solid #e0e0e0; padding-left: 0.6em; margin-left: 2.4em;} -blockquote blockquote { margin-left: 0;} -acronym { border-bottom: 1px dotted; cursor: help; } -textarea.wiki-edit {width:99%; resize:vertical;} -li p {margin-top: 0;} -div.issue {background:#ffffdd; padding:6px; margin-bottom:6px;border: 1px solid #d7d7d7;} -p.breadcrumb { font-size: 0.9em; margin: 4px 0 4px 0;} -p.subtitle { font-size: 0.9em; margin: -6px 0 12px 0; font-style: italic; } -p.footnote { font-size: 0.9em; margin-top: 0px; margin-bottom: 0px; } - -div.issue div.subject div div { padding-left: 16px; } -div.issue div.subject p {margin: 0; margin-bottom: 0.1em; font-size: 90%; color: #999;} -div.issue div.subject>div>p { margin-top: 0.5em; } -div.issue div.subject h3 {margin: 0; margin-bottom: 0.1em;} -div.issue span.private { position:relative; bottom: 2px; text-transform: uppercase; background: #d22; color: #fff; font-weight:bold; padding: 0px 2px 0px 2px; font-size: 60%; margin-right: 2px; border-radius: 2px;} -div.issue .next-prev-links {color:#999;} -div.issue table.attributes th {width:22%;} -div.issue table.attributes td {width:28%;} - -#issue_tree table.issues, #relations table.issues { border: 0; } -#issue_tree td.checkbox, #relations td.checkbox {display:none;} -#relations td.buttons {padding:0;} - -fieldset.collapsible { border-width: 1px 0 0 0; font-size: 0.9em; } -fieldset.collapsible>legend { padding-left: 16px; background: url(../images/arrow_expanded.png) no-repeat 0% 40%; cursor:pointer; } -fieldset.collapsible.collapsed>legend { background-image: url(../images/arrow_collapsed.png); } - -fieldset#date-range p { margin: 2px 0 2px 0; } -fieldset#filters table { border-collapse: collapse; } -fieldset#filters table td { padding: 0; vertical-align: middle; } -fieldset#filters tr.filter { height: 2.1em; } -fieldset#filters td.field { width:230px; } -fieldset#filters td.operator { width:180px; } -fieldset#filters td.operator select {max-width:170px;} -fieldset#filters td.values { white-space:nowrap; } -fieldset#filters td.values select {min-width:130px;} -fieldset#filters td.values input {height:1em;} -fieldset#filters td.add-filter { text-align: right; vertical-align: top; } - -.toggle-multiselect {background: url(../images/bullet_toggle_plus.png) no-repeat 0% 40%; padding-left:8px; margin-left:0; cursor:pointer;} -.buttons { font-size: 0.9em; margin-bottom: 1.4em; margin-top: 1em; } - -div#issue-changesets {float:right; width:45%; margin-left: 1em; margin-bottom: 1em; background: #fff; padding-left: 1em; font-size: 90%;} -div#issue-changesets div.changeset { padding: 4px;} -div#issue-changesets div.changeset { border-bottom: 1px solid #ddd; } -div#issue-changesets p { margin-top: 0; margin-bottom: 1em;} - -.journal ul.details img {margin:0 0 -3px 4px;} -div.journal {overflow:auto;} -div.journal.private-notes {border-left:2px solid #d22; padding-left:4px; margin-left:-6px;} - -div#activity dl, #search-results { margin-left: 2em; } -div#activity dd, #search-results dd { margin-bottom: 1em; padding-left: 18px; font-size: 0.9em; } -div#activity dt, #search-results dt { margin-bottom: 0px; padding-left: 20px; line-height: 18px; background-position: 0 50%; background-repeat: no-repeat; } -div#activity dt.me .time { border-bottom: 1px solid #999; } -div#activity dt .time { color: #777; font-size: 80%; } -div#activity dd .description, #search-results dd .description { font-style: italic; } -div#activity span.project:after, #search-results span.project:after { content: " -"; } -div#activity dd span.description, #search-results dd span.description { display:block; color: #808080; } -div#activity dt.grouped {margin-left:5em;} -div#activity dd.grouped {margin-left:9em;} - -#search-results dd { margin-bottom: 1em; padding-left: 20px; margin-left:0px; } - -div#search-results-counts {float:right;} -div#search-results-counts ul { margin-top: 0.5em; } -div#search-results-counts li { list-style-type:none; float: left; margin-left: 1em; } - -dt.issue { background-image: url(../images/ticket.png); } -dt.issue-edit { background-image: url(../images/ticket_edit.png); } -dt.issue-closed { background-image: url(../images/ticket_checked.png); } -dt.issue-note { background-image: url(../images/ticket_note.png); } -dt.changeset { background-image: url(../images/changeset.png); } -dt.news { background-image: url(../images/news.png); } -dt.message { background-image: url(../images/message.png); } -dt.reply { background-image: url(../images/comments.png); } -dt.wiki-page { background-image: url(../images/wiki_edit.png); } -dt.attachment { background-image: url(../images/attachment.png); } -dt.document { background-image: url(../images/document.png); } -dt.project { background-image: url(../images/projects.png); } -dt.time-entry { background-image: url(../images/time.png); } - -#search-results dt.issue.closed { background-image: url(../images/ticket_checked.png); } - -div#roadmap .related-issues { margin-bottom: 1em; } -div#roadmap .related-issues td.checkbox { display: none; } -div#roadmap .wiki h1:first-child { display: none; } -div#roadmap .wiki h1 { font-size: 120%; } -div#roadmap .wiki h2 { font-size: 110%; } -body.controller-versions.action-show div#roadmap .related-issues {width:70%;} - -div#version-summary { float:right; width:28%; margin-left: 16px; margin-bottom: 16px; background-color: #fff; } -div#version-summary fieldset { margin-bottom: 1em; } -div#version-summary fieldset.time-tracking table { width:100%; } -div#version-summary th, div#version-summary td.total-hours { text-align: right; } - -table#time-report td.hours, table#time-report th.period, table#time-report th.total { text-align: right; padding-right: 0.5em; } -table#time-report tbody tr.subtotal { font-style: italic; color:#777;} -table#time-report tbody tr.subtotal td.hours { color:#b0b0b0; } -table#time-report tbody tr.total { font-weight: bold; background-color:#EEEEEE; border-top:1px solid #e4e4e4;} -table#time-report .hours-dec { font-size: 0.9em; } - -div.wiki-page .contextual a {opacity: 0.4} -div.wiki-page .contextual a:hover {opacity: 1} - -form .attributes select { width: 60%; } -input#issue_subject { width: 99%; } -select#issue_done_ratio { width: 95px; } - -ul.projects {margin:0; padding-left:1em;} -ul.projects ul {padding-left:1.6em;} -ul.projects.root {margin:0; padding:0;} -ul.projects li {list-style-type:none;} - -#projects-index ul.projects ul.projects { border-left: 3px solid #e0e0e0; padding-left:1em;} -#projects-index ul.projects li.root {margin-bottom: 1em;} -#projects-index ul.projects li.child {margin-top: 1em;} -#projects-index ul.projects div.root a.project { font-family: "Trebuchet MS", Verdana, sans-serif; font-weight: bold; font-size: 16px; margin: 0 0 10px 0; } -.my-project { padding-left: 18px; background: url(../images/fav.png) no-repeat 0 50%; } - -#notified-projects ul, #tracker_project_ids ul {max-height:250px; overflow-y:auto;} - -#related-issues li img {vertical-align:middle;} - -ul.properties {padding:0; font-size: 0.9em; color: #777;} -ul.properties li {list-style-type:none;} -ul.properties li span {font-style:italic;} - -.total-hours { font-size: 110%; font-weight: bold; } -.total-hours span.hours-int { font-size: 120%; } - -.autoscroll {overflow-x: auto; padding:1px; margin-bottom: 1.2em;} -#user_login, #user_firstname, #user_lastname, #user_mail, #my_account_form select, #user_form select, #user_identity_url { width: 90%; } - -#workflow_copy_form select { width: 200px; } -table.transitions td.enabled {background: #bfb;} -table.fields_permissions select {font-size:90%} -table.fields_permissions td.readonly {background:#ddd;} -table.fields_permissions td.required {background:#d88;} - -textarea#custom_field_possible_values {width: 99%} -textarea#custom_field_default_value {width: 99%} - -input#content_comments {width: 99%} - -p.pagination {margin-top:8px; font-size: 90%} - -/***** Tabular forms ******/ -.tabular p{ - margin: 0; - padding: 3px 0 3px 0; - padding-left: 180px; /* width of left column containing the label elements */ - min-height: 1.8em; - clear:left; -} - -html>body .tabular p {overflow:hidden;} - -.tabular label{ - font-weight: bold; - float: left; - text-align: right; - /* width of left column */ - margin-left: -180px; - /* width of labels. Should be smaller than left column to create some right margin */ - width: 175px; -} - -.tabular label.floating{ - font-weight: normal; - margin-left: 0px; - text-align: left; - width: 270px; -} - -.tabular label.block{ - font-weight: normal; - margin-left: 0px !important; - text-align: left; - float: none; - display: block; - width: auto; -} - -.tabular label.inline{ - font-weight: normal; - float:none; - margin-left: 5px !important; - width: auto; -} - -label.no-css { - font-weight: inherit; - float:none; - text-align:left; - margin-left:0px; - width:auto; -} -input#time_entry_comments { width: 90%;} - -#preview fieldset {margin-top: 1em; background: url(../images/draft.png)} - -.tabular.settings p{ padding-left: 300px; } -.tabular.settings label{ margin-left: -300px; width: 295px; } -.tabular.settings textarea { width: 99%; } - -.settings.enabled_scm table {width:100%} -.settings.enabled_scm td.scm_name{ font-weight: bold; } - -fieldset.settings label { display: block; } -fieldset#notified_events .parent { padding-left: 20px; } - -span.required {color: #bb0000;} -.summary {font-style: italic;} - -#attachments_fields input.description {margin-left:4px; width:340px;} -#attachments_fields span {display:block; white-space:nowrap;} -#attachments_fields input.filename {border:0; height:1.8em; width:250px; color:#555; background-color:inherit; background:url(../images/attachment.png) no-repeat 1px 50%; padding-left:18px;} -#attachments_fields .ajax-waiting input.filename {background:url(../images/hourglass.png) no-repeat 0px 50%;} -#attachments_fields .ajax-loading input.filename {background:url(../images/loading.gif) no-repeat 0px 50%;} -#attachments_fields div.ui-progressbar { width: 100px; height:14px; margin: 2px 0 -5px 8px; display: inline-block; } -a.remove-upload {background: url(../images/delete.png) no-repeat 1px 50%; width:1px; display:inline-block; padding-left:16px;} -a.remove-upload:hover {text-decoration:none !important;} - -div.fileover { background-color: lavender; } - -div.attachments { margin-top: 12px; } -div.attachments p { margin:4px 0 2px 0; } -div.attachments img { vertical-align: middle; } -div.attachments span.author { font-size: 0.9em; color: #888; } - -div.thumbnails {margin-top:0.6em;} -div.thumbnails div {background:#fff;border:2px solid #ddd;display:inline-block;margin-right:2px;} -div.thumbnails img {margin: 3px;} - -p.other-formats { text-align: right; font-size:0.9em; color: #666; } -.other-formats span + span:before { content: "| "; } - -a.atom { background: url(../images/feed.png) no-repeat 1px 50%; padding: 2px 0px 3px 16px; } - -em.info {font-style:normal;font-size:90%;color:#888;display:block;} -em.info.error {padding-left:20px; background:url(../images/exclamation.png) no-repeat 0 50%;} - -textarea.text_cf {width:90%;} - -#tab-content-modules fieldset p {margin:3px 0 4px 0;} - -#tab-content-members .splitcontentleft, #tab-content-memberships .splitcontentleft, #tab-content-users .splitcontentleft {width: 64%;} -#tab-content-members .splitcontentright, #tab-content-memberships .splitcontentright, #tab-content-users .splitcontentright {width: 34%;} -#tab-content-members fieldset, #tab-content-memberships fieldset, #tab-content-users fieldset {padding:1em; margin-bottom: 1em;} -#tab-content-members fieldset legend, #tab-content-memberships fieldset legend, #tab-content-users fieldset legend {font-weight: bold;} -#tab-content-members fieldset label, #tab-content-memberships fieldset label, #tab-content-users fieldset label {display: block;} -#tab-content-members #principals, #tab-content-users #principals {max-height: 400px; overflow: auto;} - -#users_for_watcher {height: 200px; overflow:auto;} -#users_for_watcher label {display: block;} - -table.members td.group { padding-left: 20px; background: url(../images/group.png) no-repeat 0% 50%; } - -input#principal_search, input#user_search {width:90%} - -input.autocomplete { - background: #fff url(../images/magnifier.png) no-repeat 2px 50%; padding-left:20px; - border:1px solid #9EB1C2; border-radius:2px; height:1.5em; -} -input.autocomplete.ajax-loading { - background-image: url(../images/loading.gif); -} - -/***** Flash & error messages ****/ -#errorExplanation, div.flash, .nodata, .warning, .conflict { - padding: 4px 4px 4px 30px; - margin-bottom: 12px; - font-size: 1.1em; - border: 2px solid; -} - -div.flash {margin-top: 8px;} - -div.flash.error, #errorExplanation { - background: url(../images/exclamation.png) 8px 50% no-repeat; - background-color: #ffe3e3; - border-color: #dd0000; - color: #880000; -} - -div.flash.notice { - background: url(../images/true.png) 8px 5px no-repeat; - background-color: #dfffdf; - border-color: #9fcf9f; - color: #005f00; -} - -div.flash.warning, .conflict { - background: url(../images/warning.png) 8px 5px no-repeat; - background-color: #FFEBC1; - border-color: #FDBF3B; - color: #A6750C; - text-align: left; -} - -.nodata, .warning { - text-align: center; - background-color: #FFEBC1; - border-color: #FDBF3B; - color: #A6750C; -} - -#errorExplanation ul { font-size: 0.9em;} -#errorExplanation h2, #errorExplanation p { display: none; } - -.conflict-details {font-size:80%;} - -/***** Ajax indicator ******/ -#ajax-indicator { -position: absolute; /* fixed not supported by IE */ -background-color:#eee; -border: 1px solid #bbb; -top:35%; -left:40%; -width:20%; -font-weight:bold; -text-align:center; -padding:0.6em; -z-index:100; -opacity: 0.5; -} - -html>body #ajax-indicator { position: fixed; } - -#ajax-indicator span { -background-position: 0% 40%; -background-repeat: no-repeat; -background-image: url(../images/loading.gif); -padding-left: 26px; -vertical-align: bottom; -} - -/***** Calendar *****/ -table.cal {border-collapse: collapse; width: 100%; margin: 0px 0 6px 0;border: 1px solid #d7d7d7;} -table.cal thead th {width: 14%; background-color:#EEEEEE; padding: 4px; } -table.cal thead th.week-number {width: auto;} -table.cal tbody tr {height: 100px;} -table.cal td {border: 1px solid #d7d7d7; vertical-align: top; font-size: 0.9em;} -table.cal td.week-number { background-color:#EEEEEE; padding: 4px; border:none; font-size: 1em;} -table.cal td p.day-num {font-size: 1.1em; text-align:right;} -table.cal td.odd p.day-num {color: #bbb;} -table.cal td.today {background:#ffffdd;} -table.cal td.today p.day-num {font-weight: bold;} -table.cal .starting a, p.cal.legend .starting {background: url(../images/bullet_go.png) no-repeat -1px -2px; padding-left:16px;} -table.cal .ending a, p.cal.legend .ending {background: url(../images/bullet_end.png) no-repeat -1px -2px; padding-left:16px;} -table.cal .starting.ending a, p.cal.legend .starting.ending {background: url(../images/bullet_diamond.png) no-repeat -1px -2px; padding-left:16px;} -p.cal.legend span {display:block;} - -/***** Tooltips ******/ -.tooltip{position:relative;z-index:24;} -.tooltip:hover{z-index:25;color:#000;} -.tooltip span.tip{display: none; text-align:left;} - -div.tooltip:hover span.tip{ -display:block; -position:absolute; -top:12px; left:24px; width:270px; -border:1px solid #555; -background-color:#fff; -padding: 4px; -font-size: 0.8em; -color:#505050; -} - -img.ui-datepicker-trigger { - cursor: pointer; - vertical-align: middle; - margin-left: 4px; -} - -/***** Progress bar *****/ -table.progress { - border-collapse: collapse; - border-spacing: 0pt; - empty-cells: show; - text-align: center; - float:left; - margin: 1px 6px 1px 0px; -} - -table.progress td { height: 1em; } -table.progress td.closed { background: #BAE0BA none repeat scroll 0%; } -table.progress td.done { background: #D3EDD3 none repeat scroll 0%; } -table.progress td.todo { background: #eee none repeat scroll 0%; } -p.percent {font-size: 80%;} -p.progress-info {clear: left; font-size: 80%; margin-top:-4px; color:#777;} - -#roadmap table.progress td { height: 1.2em; } -/***** Tabs *****/ -#content .tabs {height: 2.6em; margin-bottom:1.2em; position:relative; overflow:hidden;} -#content .tabs ul {margin:0; position:absolute; bottom:0; padding-left:0.5em; width: 2000px; border-bottom: 1px solid #bbbbbb;} -#content .tabs ul li { - float:left; - list-style-type:none; - white-space:nowrap; - margin-right:4px; - background:#fff; - position:relative; - margin-bottom:-1px; -} -#content .tabs ul li a{ - display:block; - font-size: 0.9em; - text-decoration:none; - line-height:1.3em; - padding:4px 6px 4px 6px; - border: 1px solid #ccc; - border-bottom: 1px solid #bbbbbb; - background-color: #f6f6f6; - color:#999; - font-weight:bold; - border-top-left-radius:3px; - border-top-right-radius:3px; -} - -#content .tabs ul li a:hover { - background-color: #ffffdd; - text-decoration:none; -} - -#content .tabs ul li a.selected { - background-color: #fff; - border: 1px solid #bbbbbb; - border-bottom: 1px solid #fff; - color:#444; -} - -#content .tabs ul li a.selected:hover {background-color: #fff;} - -div.tabs-buttons { position:absolute; right: 0; width: 48px; height: 24px; background: white; bottom: 0; border-bottom: 1px solid #bbbbbb; } - -button.tab-left, button.tab-right { - font-size: 0.9em; - cursor: pointer; - height:24px; - border: 1px solid #ccc; - border-bottom: 1px solid #bbbbbb; - position:absolute; - padding:4px; - width: 20px; - bottom: -1px; -} - -button.tab-left { - right: 20px; - background: #eeeeee url(../images/bullet_arrow_left.png) no-repeat 50% 50%; - border-top-left-radius:3px; -} - -button.tab-right { - right: 0; - background: #eeeeee url(../images/bullet_arrow_right.png) no-repeat 50% 50%; - border-top-right-radius:3px; -} - -/***** Diff *****/ -.diff_out { background: #fcc; } -.diff_out span { background: #faa; } -.diff_in { background: #cfc; } -.diff_in span { background: #afa; } - -.text-diff { - padding: 1em; - background-color:#f6f6f6; - color:#505050; - border: 1px solid #e4e4e4; -} - -/***** Wiki *****/ -div.wiki table { - border-collapse: collapse; - margin-bottom: 1em; -} - -div.wiki table, div.wiki td, div.wiki th { - border: 1px solid #bbb; - padding: 4px; -} - -div.wiki .noborder, div.wiki .noborder td, div.wiki .noborder th {border:0;} - -div.wiki .external { - background-position: 0% 60%; - background-repeat: no-repeat; - padding-left: 12px; - background-image: url(../images/external.png); -} - -div.wiki a.new {color: #b73535;} - -div.wiki ul, div.wiki ol {margin-bottom:1em;} - -div.wiki pre { - margin: 1em 1em 1em 1.6em; - padding: 8px; - background-color: #fafafa; - border: 1px solid #e2e2e2; - width:auto; - overflow-x: auto; - overflow-y: hidden; -} - -div.wiki ul.toc { - background-color: #ffffdd; - border: 1px solid #e4e4e4; - padding: 4px; - line-height: 1.2em; - margin-bottom: 12px; - margin-right: 12px; - margin-left: 0; - display: table -} -* html div.wiki ul.toc { width: 50%; } /* IE6 doesn't autosize div */ - -div.wiki ul.toc.right { float: right; margin-left: 12px; margin-right: 0; width: auto; } -div.wiki ul.toc.left { float: left; margin-right: 12px; margin-left: 0; width: auto; } -div.wiki ul.toc ul { margin: 0; padding: 0; } -div.wiki ul.toc li {list-style-type:none; margin: 0; font-size:12px;} -div.wiki ul.toc li li {margin-left: 1.5em; font-size:10px;} -div.wiki ul.toc a { - font-size: 0.9em; - font-weight: normal; - text-decoration: none; - color: #606060; -} -div.wiki ul.toc a:hover { color: #c61a1a; text-decoration: underline;} - -a.wiki-anchor { display: none; margin-left: 6px; text-decoration: none; } -a.wiki-anchor:hover { color: #aaa !important; text-decoration: none; } -h1:hover a.wiki-anchor, h2:hover a.wiki-anchor, h3:hover a.wiki-anchor { display: inline; color: #ddd; } - -div.wiki img { vertical-align: middle; } - -/***** My page layout *****/ -.block-receiver { - border:1px dashed #c0c0c0; - margin-bottom: 20px; - padding: 15px 0 15px 0; -} - -.mypage-box { - margin:0 0 20px 0; - color:#505050; - line-height:1.5em; -} - -.handle {cursor: move;} - -a.close-icon { - display:block; - margin-top:3px; - overflow:hidden; - width:12px; - height:12px; - background-repeat: no-repeat; - cursor:pointer; - background-image:url('../images/close.png'); -} -a.close-icon:hover {background-image:url('../images/close_hl.png');} - -/***** Gantt chart *****/ -.gantt_hdr { - position:absolute; - top:0; - height:16px; - border-top: 1px solid #c0c0c0; - border-bottom: 1px solid #c0c0c0; - border-right: 1px solid #c0c0c0; - text-align: center; - overflow: hidden; -} - -.gantt_hdr.nwday {background-color:#f1f1f1;} - -.gantt_subjects { font-size: 0.8em; } -.gantt_subjects div { line-height:16px;height:16px;overflow:hidden;white-space:nowrap;text-overflow: ellipsis; } - -.task { - position: absolute; - height:8px; - font-size:0.8em; - color:#888; - padding:0; - margin:0; - line-height:16px; - white-space:nowrap; -} - -.task.label {width:100%;} -.task.label.project, .task.label.version { font-weight: bold; } - -.task_late { background:#f66 url(../images/task_late.png); border: 1px solid #f66; } -.task_done { background:#00c600 url(../images/task_done.png); border: 1px solid #00c600; } -.task_todo { background:#aaa url(../images/task_todo.png); border: 1px solid #aaa; } - -.task_todo.parent { background: #888; border: 1px solid #888; height: 3px;} -.task_late.parent, .task_done.parent { height: 3px;} -.task.parent.marker.starting { position: absolute; background: url(../images/task_parent_end.png) no-repeat 0 0; width: 8px; height: 16px; margin-left: -4px; left: 0px; top: -1px;} -.task.parent.marker.ending { position: absolute; background: url(../images/task_parent_end.png) no-repeat 0 0; width: 8px; height: 16px; margin-left: -4px; right: 0px; top: -1px;} - -.version.task_late { background:#f66 url(../images/milestone_late.png); border: 1px solid #f66; height: 2px; margin-top: 3px;} -.version.task_done { background:#00c600 url(../images/milestone_done.png); border: 1px solid #00c600; height: 2px; margin-top: 3px;} -.version.task_todo { background:#fff url(../images/milestone_todo.png); border: 1px solid #fff; height: 2px; margin-top: 3px;} -.version.marker { background-image:url(../images/version_marker.png); background-repeat: no-repeat; border: 0; margin-left: -4px; margin-top: 1px; } - -.project.task_late { background:#f66 url(../images/milestone_late.png); border: 1px solid #f66; height: 2px; margin-top: 3px;} -.project.task_done { background:#00c600 url(../images/milestone_done.png); border: 1px solid #00c600; height: 2px; margin-top: 3px;} -.project.task_todo { background:#fff url(../images/milestone_todo.png); border: 1px solid #fff; height: 2px; margin-top: 3px;} -.project.marker { background-image:url(../images/project_marker.png); background-repeat: no-repeat; border: 0; margin-left: -4px; margin-top: 1px; } - -.version-behind-schedule a, .issue-behind-schedule a {color: #f66914;} -.version-overdue a, .issue-overdue a, .project-overdue a {color: #f00;} - -/***** Icons *****/ -.icon { - background-position: 0% 50%; - background-repeat: no-repeat; - padding-left: 20px; - padding-top: 2px; - padding-bottom: 3px; -} - -.icon-add { background-image: url(../images/add.png); } -.icon-edit { background-image: url(../images/edit.png); } -.icon-copy { background-image: url(../images/copy.png); } -.icon-duplicate { background-image: url(../images/duplicate.png); } -.icon-del { background-image: url(../images/delete.png); } -.icon-move { background-image: url(../images/move.png); } -.icon-save { background-image: url(../images/save.png); } -.icon-cancel { background-image: url(../images/cancel.png); } -.icon-multiple { background-image: url(../images/table_multiple.png); } -.icon-folder { background-image: url(../images/folder.png); } -.open .icon-folder { background-image: url(../images/folder_open.png); } -.icon-package { background-image: url(../images/package.png); } -.icon-user { background-image: url(../images/user.png); } -.icon-projects { background-image: url(../images/projects.png); } -.icon-help { background-image: url(../images/help.png); } -.icon-attachment { background-image: url(../images/attachment.png); } -.icon-history { background-image: url(../images/history.png); } -.icon-time { background-image: url(../images/time.png); } -.icon-time-add { background-image: url(../images/time_add.png); } -.icon-stats { background-image: url(../images/stats.png); } -.icon-warning { background-image: url(../images/warning.png); } -.icon-fav { background-image: url(../images/fav.png); } -.icon-fav-off { background-image: url(../images/fav_off.png); } -.icon-reload { background-image: url(../images/reload.png); } -.icon-lock { background-image: url(../images/locked.png); } -.icon-unlock { background-image: url(../images/unlock.png); } -.icon-checked { background-image: url(../images/true.png); } -.icon-details { background-image: url(../images/zoom_in.png); } -.icon-report { background-image: url(../images/report.png); } -.icon-comment { background-image: url(../images/comment.png); } -.icon-summary { background-image: url(../images/lightning.png); } -.icon-server-authentication { background-image: url(../images/server_key.png); } -.icon-issue { background-image: url(../images/ticket.png); } -.icon-zoom-in { background-image: url(../images/zoom_in.png); } -.icon-zoom-out { background-image: url(../images/zoom_out.png); } -.icon-passwd { background-image: url(../images/textfield_key.png); } -.icon-test { background-image: url(../images/bullet_go.png); } - -.icon-file { background-image: url(../images/files/default.png); } -.icon-file.text-plain { background-image: url(../images/files/text.png); } -.icon-file.text-x-c { background-image: url(../images/files/c.png); } -.icon-file.text-x-csharp { background-image: url(../images/files/csharp.png); } -.icon-file.text-x-java { background-image: url(../images/files/java.png); } -.icon-file.text-x-javascript { background-image: url(../images/files/js.png); } -.icon-file.text-x-php { background-image: url(../images/files/php.png); } -.icon-file.text-x-ruby { background-image: url(../images/files/ruby.png); } -.icon-file.text-xml { background-image: url(../images/files/xml.png); } -.icon-file.text-css { background-image: url(../images/files/css.png); } -.icon-file.text-html { background-image: url(../images/files/html.png); } -.icon-file.image-gif { background-image: url(../images/files/image.png); } -.icon-file.image-jpeg { background-image: url(../images/files/image.png); } -.icon-file.image-png { background-image: url(../images/files/image.png); } -.icon-file.image-tiff { background-image: url(../images/files/image.png); } -.icon-file.application-pdf { background-image: url(../images/files/pdf.png); } -.icon-file.application-zip { background-image: url(../images/files/zip.png); } -.icon-file.application-x-gzip { background-image: url(../images/files/zip.png); } - -img.gravatar { - padding: 2px; - border: solid 1px #d5d5d5; - background: #fff; - vertical-align: middle; -} - -div.issue img.gravatar { - float: left; - margin: 0 6px 0 0; - padding: 5px; -} - -div.issue table img.gravatar { - height: 14px; - width: 14px; - padding: 2px; - float: left; - margin: 0 0.5em 0 0; -} - -h2 img.gravatar {margin: -2px 4px -4px 0;} -h3 img.gravatar {margin: -4px 4px -4px 0;} -h4 img.gravatar {margin: -6px 4px -4px 0;} -td.username img.gravatar {margin: 0 0.5em 0 0; vertical-align: top;} -#activity dt img.gravatar {float: left; margin: 0 1em 1em 0;} -/* Used on 12px Gravatar img tags without the icon background */ -.icon-gravatar {float: left; margin-right: 4px;} - -#activity dt, .journal {clear: left;} - -.journal-link {float: right;} - -h2 img { vertical-align:middle; } - -.hascontextmenu { cursor: context-menu; } - -/************* CodeRay styles *************/ -.syntaxhl div {display: inline;} -.syntaxhl .line-numbers {padding: 2px 4px 2px 4px; background-color: #eee; margin:0px 5px 0px 0px;} -.syntaxhl .code pre { overflow: auto } -.syntaxhl .debug { color: white !important; background: blue !important; } - -.syntaxhl .annotation { color:#007 } -.syntaxhl .attribute-name { color:#b48 } -.syntaxhl .attribute-value { color:#700 } -.syntaxhl .binary { color:#509 } -.syntaxhl .char .content { color:#D20 } -.syntaxhl .char .delimiter { color:#710 } -.syntaxhl .char { color:#D20 } -.syntaxhl .class { color:#258; font-weight:bold } -.syntaxhl .class-variable { color:#369 } -.syntaxhl .color { color:#0A0 } -.syntaxhl .comment { color:#385 } -.syntaxhl .comment .char { color:#385 } -.syntaxhl .comment .delimiter { color:#385 } -.syntaxhl .complex { color:#A08 } -.syntaxhl .constant { color:#258; font-weight:bold } -.syntaxhl .decorator { color:#B0B } -.syntaxhl .definition { color:#099; font-weight:bold } -.syntaxhl .delimiter { color:black } -.syntaxhl .directive { color:#088; font-weight:bold } -.syntaxhl .doc { color:#970 } -.syntaxhl .doc-string { color:#D42; font-weight:bold } -.syntaxhl .doctype { color:#34b } -.syntaxhl .entity { color:#800; font-weight:bold } -.syntaxhl .error { color:#F00; background-color:#FAA } -.syntaxhl .escape { color:#666 } -.syntaxhl .exception { color:#C00; font-weight:bold } -.syntaxhl .float { color:#06D } -.syntaxhl .function { color:#06B; font-weight:bold } -.syntaxhl .global-variable { color:#d70 } -.syntaxhl .hex { color:#02b } -.syntaxhl .imaginary { color:#f00 } -.syntaxhl .include { color:#B44; font-weight:bold } -.syntaxhl .inline { background-color: hsla(0,0%,0%,0.07); color: black } -.syntaxhl .inline-delimiter { font-weight: bold; color: #666 } -.syntaxhl .instance-variable { color:#33B } -.syntaxhl .integer { color:#06D } -.syntaxhl .key .char { color: #60f } -.syntaxhl .key .delimiter { color: #404 } -.syntaxhl .key { color: #606 } -.syntaxhl .keyword { color:#939; font-weight:bold } -.syntaxhl .label { color:#970; font-weight:bold } -.syntaxhl .local-variable { color:#963 } -.syntaxhl .namespace { color:#707; font-weight:bold } -.syntaxhl .octal { color:#40E } -.syntaxhl .operator { } -.syntaxhl .predefined { color:#369; font-weight:bold } -.syntaxhl .predefined-constant { color:#069 } -.syntaxhl .predefined-type { color:#0a5; font-weight:bold } -.syntaxhl .preprocessor { color:#579 } -.syntaxhl .pseudo-class { color:#00C; font-weight:bold } -.syntaxhl .regexp .content { color:#808 } -.syntaxhl .regexp .delimiter { color:#404 } -.syntaxhl .regexp .modifier { color:#C2C } -.syntaxhl .regexp { background-color:hsla(300,100%,50%,0.06); } -.syntaxhl .reserved { color:#080; font-weight:bold } -.syntaxhl .shell .content { color:#2B2 } -.syntaxhl .shell .delimiter { color:#161 } -.syntaxhl .shell { background-color:hsla(120,100%,50%,0.06); } -.syntaxhl .string .char { color: #46a } -.syntaxhl .string .content { color: #46a } -.syntaxhl .string .delimiter { color: #46a } -.syntaxhl .string .modifier { color: #46a } -.syntaxhl .symbol .content { color:#d33 } -.syntaxhl .symbol .delimiter { color:#d33 } -.syntaxhl .symbol { color:#d33 } -.syntaxhl .tag { color:#070 } -.syntaxhl .type { color:#339; font-weight:bold } -.syntaxhl .value { color: #088; } -.syntaxhl .variable { color:#037 } - -.syntaxhl .insert { background: hsla(120,100%,50%,0.12) } -.syntaxhl .delete { background: hsla(0,100%,50%,0.12) } -.syntaxhl .change { color: #bbf; background: #007; } -.syntaxhl .head { color: #f8f; background: #505 } -.syntaxhl .head .filename { color: white; } - -.syntaxhl .delete .eyecatcher { background-color: hsla(0,100%,50%,0.2); border: 1px solid hsla(0,100%,45%,0.5); margin: -1px; border-bottom: none; border-top-left-radius: 5px; border-top-right-radius: 5px; } -.syntaxhl .insert .eyecatcher { background-color: hsla(120,100%,50%,0.2); border: 1px solid hsla(120,100%,25%,0.5); margin: -1px; border-top: none; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; } - -.syntaxhl .insert .insert { color: #0c0; background:transparent; font-weight:bold } -.syntaxhl .delete .delete { color: #c00; background:transparent; font-weight:bold } -.syntaxhl .change .change { color: #88f } -.syntaxhl .head .head { color: #f4f } - -/***** Media print specific styles *****/ -@media print { - #top-menu, #header, #main-menu, #sidebar, #footer, .contextual, .other-formats { display:none; } - #main { background: #fff; } - #content { width: 99%; margin: 0; padding: 0; border: 0; background: #fff; overflow: visible !important;} - #wiki_add_attachment { display:none; } - .hide-when-print { display: none; } - .autoscroll {overflow-x: visible;} - table.list {margin-top:0.5em;} - table.list th, table.list td {border: 1px solid #aaa;} -} - -/* Accessibility specific styles */ -.hidden-for-sighted { - position:absolute; - left:-10000px; - top:auto; - width:1px; - height:1px; - overflow:hidden; -} diff --git a/public/stylesheets/nyan.css b/public/stylesheets/nyan.css index dfcf890f..b041f43a 100644 --- a/public/stylesheets/nyan.css +++ b/public/stylesheets/nyan.css @@ -1,3 +1,9 @@ +/* Temporary +*******************************************************************************/ +.frame-wiki { + padding: 0 10px; +} + /* TODO: base/common/page 准备封装一些基本样式组合调用 参考YUI *******************************************************************************/ * { diff --git a/public/themes/redpenny-master/stylesheets/application.css b/public/themes/redpenny-master/stylesheets/application.css index 0d7297c7..082a0ac1 100644 --- a/public/themes/redpenny-master/stylesheets/application.css +++ b/public/themes/redpenny-master/stylesheets/application.css @@ -524,19 +524,8 @@ ul.projects li.root margin:4px 20px 20px; padding-bottom:15px; text-align:left - /*font-size: 18px;*/ } -#footer a:hover -{ - /*background:#666 none repeat scroll 0 0;*/ - /*color:#FFF!important*/ -} - -#footer a:link,#footer a:visited -{ - /*color:#666*/ -} #footer .bgr:after { @@ -544,60 +533,6 @@ ul.projects li.root float:right } -h1,h2,h3,h4 -{ - font-family:'微软雅黑',"PT Sans","Lucida Grande",arial,sans-serif /*modify by men*/ -} - -h1 -{ - font-size:24px; /*工作台界面框框大小*/ - font-weight:400; - margin:0 0 0 .25em; - padding:0 0 10px; - text-align:left -} - -h2,h3,h4,.wiki h1,.wiki h2,.wiki h3 -{ - border-bottom:0 -} - -h2,.wiki h1 -{ - background-color:#e0e0e0; /*第三层背景非导航条*/ - margin:-6px -10px 10px; - padding:10px 20px; - font-size:14px; - color:#fff; - border-top:1px #ddd solid -} - -.wiki h1 -{ - font-family:"PT Sans","Trebuchet MS",Helvetica,sans-serif; - font-weight:700 -} - -.wiki h2 -{ - background-color:transparent -} - -div.issue div.wiki h3 -{ - text-decoration:underline -} - -h3,h4 -{ - font-weight:400 -} - -div.wiki h3,div.wiki h4 -{ - font-weight:700 -} #sidebar h3 {