@@ -1,27 +1,31 | |||||
1 | <div class="contextual"> |
|
1 | <div class="contextual"> | |
2 | <%= link_to(l(:label_page_index), {:action => 'special', :page => 'Page_index'}, :class => 'icon icon-index') %> |
|
2 | <%= link_to(l(:label_page_index), {:action => 'special', :page => 'Page_index'}, :class => 'icon icon-index') %> | |
3 | </div> |
|
3 | </div> | |
4 |
|
4 | |||
5 | <h2><%= @page.pretty_title %></h2> |
|
5 | <h2><%= @page.pretty_title %></h2> | |
6 |
|
6 | |||
7 | <% form_for :content, @content, :url => {:action => 'edit', :page => @page.title}, :html => {:id => 'wiki_form'} do |f| %> |
|
7 | <% form_for :content, @content, :url => {:action => 'edit', :page => @page.title}, :html => {:id => 'wiki_form'} do |f| %> | |
8 | <%= f.hidden_field :version %> |
|
8 | <%= f.hidden_field :version %> | |
9 | <%= error_messages_for 'content' %> |
|
9 | <%= error_messages_for 'content' %> | |
10 | <div class="contextual"> |
|
10 | <div class="contextual"> | |
11 | <%= l(:setting_text_formatting) %>: |
|
11 | <%= l(:setting_text_formatting) %>: | |
12 | <%= link_to l(:label_help), {:controller => 'help', :ctrl => 'wiki', :page => 'syntax' }, |
|
12 | <%= link_to l(:label_help), {:controller => 'help', :ctrl => 'wiki', :page => 'syntax' }, | |
13 | :onclick => "window.open('#{ url_for :controller => 'help', :ctrl => 'wiki', :page => 'syntax' }', '', 'resizable=yes, location=no, width=300, height=500, menubar=no, status=no, scrollbars=yes'); return false;" %> |
|
13 | :onclick => "window.open('#{ url_for :controller => 'help', :ctrl => 'wiki', :page => 'syntax' }', '', 'resizable=yes, location=no, width=300, height=500, menubar=no, status=no, scrollbars=yes'); return false;" %> | |
14 | </div> |
|
14 | </div> | |
15 | <p><%= f.text_area :text, :cols => 100, :rows => 25, :class => 'wiki-edit' %></p> |
|
15 | <p><%= f.text_area :text, :cols => 100, :rows => 25, :class => 'wiki-edit' %></p> | |
16 | <p><label><%= l(:field_comments) %></label><br /><%= f.text_field :comments, :size => 120 %></p> |
|
16 | <p><label><%= l(:field_comments) %></label><br /><%= f.text_field :comments, :size => 120 %></p> | |
17 | <p><%= submit_tag l(:button_save) %> |
|
17 | <p><%= submit_tag l(:button_save) %> | |
18 | <%= link_to_remote l(:label_preview), |
|
18 | <%= link_to_remote l(:label_preview), | |
19 | { :url => { :controller => 'wiki', :action => 'preview', :id => @project, :page => @page.title }, |
|
19 | { :url => { :controller => 'wiki', :action => 'preview', :id => @project, :page => @page.title }, | |
20 | :method => 'post', |
|
20 | :method => 'post', | |
21 | :update => 'preview', |
|
21 | :update => 'preview', | |
22 | :with => "Form.serialize('wiki_form')" |
|
22 | :with => "Form.serialize('wiki_form')" | |
23 | } %></p> |
|
23 | } %></p> | |
24 | <%= wikitoolbar_for 'content_text' %> |
|
24 | <%= wikitoolbar_for 'content_text' %> | |
25 | <% end %> |
|
25 | <% end %> | |
26 |
|
26 | |||
27 | <div id="preview" class="wiki"></div> |
|
27 | <div id="preview" class="wiki"></div> | |
|
28 | ||||
|
29 | <% content_for :header_tags do %> | |||
|
30 | <%= stylesheet_link_tag 'scm' %> | |||
|
31 | <% end %> |
@@ -1,39 +1,43 | |||||
1 | <div class="contextual"> |
|
1 | <div class="contextual"> | |
2 | <%= link_to_if_authorized(l(:button_edit), {:action => 'edit', :page => @page.title}, :class => 'icon icon-edit') if @content.version == @page.content.version %> |
|
2 | <%= link_to_if_authorized(l(:button_edit), {:action => 'edit', :page => @page.title}, :class => 'icon icon-edit') if @content.version == @page.content.version %> | |
3 | <%= link_to_if_authorized(l(:button_delete), {:action => 'destroy', :page => @page.title}, :method => :post, :confirm => l(:text_are_you_sure), :class => 'icon icon-del') %> |
|
3 | <%= link_to_if_authorized(l(:button_delete), {:action => 'destroy', :page => @page.title}, :method => :post, :confirm => l(:text_are_you_sure), :class => 'icon icon-del') %> | |
4 | <%= link_to_if_authorized(l(:button_rollback), {:action => 'edit', :page => @page.title, :version => @content.version }, :class => 'icon icon-cancel') if @content.version < @page.content.version %> |
|
4 | <%= link_to_if_authorized(l(:button_rollback), {:action => 'edit', :page => @page.title, :version => @content.version }, :class => 'icon icon-cancel') if @content.version < @page.content.version %> | |
5 | <%= link_to(l(:label_history), {:action => 'history', :page => @page.title}, :class => 'icon icon-history') %> |
|
5 | <%= link_to(l(:label_history), {:action => 'history', :page => @page.title}, :class => 'icon icon-history') %> | |
6 | <%= link_to(l(:label_page_index), {:action => 'special', :page => 'Page_index'}, :class => 'icon icon-index') %> |
|
6 | <%= link_to(l(:label_page_index), {:action => 'special', :page => 'Page_index'}, :class => 'icon icon-index') %> | |
7 | </div> |
|
7 | </div> | |
8 |
|
8 | |||
9 | <% if @content.version != @page.content.version %> |
|
9 | <% if @content.version != @page.content.version %> | |
10 | <p> |
|
10 | <p> | |
11 | <%= link_to(('« ' + l(:label_previous)), :action => 'index', :page => @page.title, :version => (@content.version - 1)) + " - " if @content.version > 1 %> |
|
11 | <%= link_to(('« ' + l(:label_previous)), :action => 'index', :page => @page.title, :version => (@content.version - 1)) + " - " if @content.version > 1 %> | |
12 | <%= "#{l(:label_version)} #{@content.version}/#{@page.content.version}" %> |
|
12 | <%= "#{l(:label_version)} #{@content.version}/#{@page.content.version}" %> | |
13 | <%= '(' + link_to('diff', :controller => 'wiki', :action => 'diff', :page => @page.title, :version => @content.version) + ')' if @content.version > 1 %> - |
|
13 | <%= '(' + link_to('diff', :controller => 'wiki', :action => 'diff', :page => @page.title, :version => @content.version) + ')' if @content.version > 1 %> - | |
14 | <%= link_to((l(:label_next) + ' »'), :action => 'index', :page => @page.title, :version => (@content.version + 1)) + " - " if @content.version < @page.content.version %> |
|
14 | <%= link_to((l(:label_next) + ' »'), :action => 'index', :page => @page.title, :version => (@content.version + 1)) + " - " if @content.version < @page.content.version %> | |
15 | <%= link_to(l(:label_current_version), :action => 'index', :page => @page.title) %> |
|
15 | <%= link_to(l(:label_current_version), :action => 'index', :page => @page.title) %> | |
16 | <br /> |
|
16 | <br /> | |
17 | <em><%= @content.author ? @content.author.name : "anonyme" %>, <%= format_time(@content.updated_on) %> </em><br /> |
|
17 | <em><%= @content.author ? @content.author.name : "anonyme" %>, <%= format_time(@content.updated_on) %> </em><br /> | |
18 | <%=h @content.comments %> |
|
18 | <%=h @content.comments %> | |
19 | </p> |
|
19 | </p> | |
20 | <hr /> |
|
20 | <hr /> | |
21 | <% end %> |
|
21 | <% end %> | |
22 |
|
22 | |||
23 | <%= render(:partial => "wiki/content", :locals => {:content => @content}) %> |
|
23 | <%= render(:partial => "wiki/content", :locals => {:content => @content}) %> | |
24 |
|
24 | |||
25 | <%= link_to_attachments @page.attachments, :delete_url => (authorize_for('wiki', 'destroy_attachment') ? {:controller => 'wiki', :action => 'destroy_attachment', :page => @page.title} : nil) %> |
|
25 | <%= link_to_attachments @page.attachments, :delete_url => (authorize_for('wiki', 'destroy_attachment') ? {:controller => 'wiki', :action => 'destroy_attachment', :page => @page.title} : nil) %> | |
26 |
|
26 | |||
27 | <div class="contextual"> |
|
27 | <div class="contextual"> | |
28 | <%= l(:label_export_to) %> |
|
28 | <%= l(:label_export_to) %> | |
29 | <%= link_to 'HTML', {:export => 'html', :version => @content.version}, :class => 'icon icon-html' %>, |
|
29 | <%= link_to 'HTML', {:export => 'html', :version => @content.version}, :class => 'icon icon-html' %>, | |
30 | <%= link_to 'TXT', {:export => 'txt', :version => @content.version}, :class => 'icon icon-txt' %> |
|
30 | <%= link_to 'TXT', {:export => 'txt', :version => @content.version}, :class => 'icon icon-txt' %> | |
31 | </div> |
|
31 | </div> | |
32 |
|
32 | |||
33 | <% if authorize_for('wiki', 'add_attachment') %> |
|
33 | <% if authorize_for('wiki', 'add_attachment') %> | |
34 | <p><%= toggle_link l(:label_attachment_new), "add_attachment_form" %></p> |
|
34 | <p><%= toggle_link l(:label_attachment_new), "add_attachment_form" %></p> | |
35 | <% form_tag({ :controller => 'wiki', :action => 'add_attachment', :page => @page.title }, :multipart => true, :class => "tabular", :id => "add_attachment_form", :style => "display:none;") do %> |
|
35 | <% form_tag({ :controller => 'wiki', :action => 'add_attachment', :page => @page.title }, :multipart => true, :class => "tabular", :id => "add_attachment_form", :style => "display:none;") do %> | |
36 | <%= render :partial => 'attachments/form' %> |
|
36 | <%= render :partial => 'attachments/form' %> | |
37 | <%= submit_tag l(:button_add) %> |
|
37 | <%= submit_tag l(:button_add) %> | |
38 | <% end %> |
|
38 | <% end %> | |
39 | <% end %> |
|
39 | <% end %> | |
|
40 | ||||
|
41 | <% content_for :header_tags do %> | |||
|
42 | <%= stylesheet_link_tag 'scm' %> | |||
|
43 | <% end %> |
@@ -1,79 +1,95 | |||||
1 | require 'redcloth' |
|
1 | require 'redcloth' | |
|
2 | require 'coderay' | |||
2 |
|
3 | |||
3 | module Redmine |
|
4 | module Redmine | |
4 | module WikiFormatting |
|
5 | module WikiFormatting | |
5 |
|
6 | |||
6 | private |
|
7 | private | |
7 |
|
8 | |||
8 | class TextileFormatter < RedCloth |
|
9 | class TextileFormatter < RedCloth | |
9 | RULES = [:inline_auto_link, :inline_auto_mailto, :textile ] |
|
10 | RULES = [:inline_auto_link, :inline_auto_mailto, :textile ] | |
10 |
|
11 | |||
11 | def initialize(*args) |
|
12 | def initialize(*args) | |
12 | super |
|
13 | super | |
13 | self.hard_breaks=true |
|
14 | self.hard_breaks=true | |
14 | end |
|
15 | end | |
15 |
|
16 | |||
16 | def to_html |
|
17 | def to_html | |
17 | super(*RULES).to_s |
|
18 | super(*RULES).to_s | |
18 | end |
|
19 | end | |
19 |
|
20 | |||
20 | private |
|
21 | private | |
21 |
|
22 | |||
22 | # Patch for RedCloth. Fixed in RedCloth r128 but _why hasn't released it yet. |
|
23 | # Patch for RedCloth. Fixed in RedCloth r128 but _why hasn't released it yet. | |
23 | # <a href="http://code.whytheluckystiff.net/redcloth/changeset/128">http://code.whytheluckystiff.net/redcloth/changeset/128</a> |
|
24 | # <a href="http://code.whytheluckystiff.net/redcloth/changeset/128">http://code.whytheluckystiff.net/redcloth/changeset/128</a> | |
24 | def hard_break( text ) |
|
25 | def hard_break( text ) | |
25 | text.gsub!( /(.)\n(?!\n|\Z| *([#*=]+(\s|$)|[{|]))/, "\\1<br />" ) if hard_breaks |
|
26 | text.gsub!( /(.)\n(?!\n|\Z| *([#*=]+(\s|$)|[{|]))/, "\\1<br />" ) if hard_breaks | |
26 | end |
|
27 | end | |
27 |
|
28 | |||
|
29 | # Patch to add code highlighting support to RedCloth | |||
|
30 | def smooth_offtags( text ) | |||
|
31 | unless @pre_list.empty? | |||
|
32 | ## replace <pre> content | |||
|
33 | text.gsub!(/<redpre#(\d+)>/) do | |||
|
34 | content = @pre_list[$1.to_i] | |||
|
35 | if content.match(/<code\s+class="(\w+)">\s?(.+)/m) | |||
|
36 | content = "<code class=\"#{$1} CodeRay\">" + | |||
|
37 | CodeRay.scan($2, $1).html(:escape => false, :line_numbers => :inline) | |||
|
38 | end | |||
|
39 | content | |||
|
40 | end | |||
|
41 | end | |||
|
42 | end | |||
|
43 | ||||
28 | AUTO_LINK_RE = %r{ |
|
44 | AUTO_LINK_RE = %r{ | |
29 | ( # leading text |
|
45 | ( # leading text | |
30 | <\w+.*?>| # leading HTML tag, or |
|
46 | <\w+.*?>| # leading HTML tag, or | |
31 | [^=<>!:'"/]| # leading punctuation, or |
|
47 | [^=<>!:'"/]| # leading punctuation, or | |
32 | ^ # beginning of line |
|
48 | ^ # beginning of line | |
33 | ) |
|
49 | ) | |
34 | ( |
|
50 | ( | |
35 | (?:https?://)| # protocol spec, or |
|
51 | (?:https?://)| # protocol spec, or | |
36 | (?:www\.) # www.* |
|
52 | (?:www\.) # www.* | |
37 | ) |
|
53 | ) | |
38 | ( |
|
54 | ( | |
39 | [-\w]+ # subdomain or domain |
|
55 | [-\w]+ # subdomain or domain | |
40 | (?:\.[-\w]+)* # remaining subdomains or domain |
|
56 | (?:\.[-\w]+)* # remaining subdomains or domain | |
41 | (?::\d+)? # port |
|
57 | (?::\d+)? # port | |
42 | (?:/(?:(?:[~\w\+%-]|(?:[,.;:][^\s$]))+)?)* # path |
|
58 | (?:/(?:(?:[~\w\+%-]|(?:[,.;:][^\s$]))+)?)* # path | |
43 | (?:\?[\w\+%&=.;-]+)? # query string |
|
59 | (?:\?[\w\+%&=.;-]+)? # query string | |
44 | (?:\#[\w\-]*)? # trailing anchor |
|
60 | (?:\#[\w\-]*)? # trailing anchor | |
45 | ) |
|
61 | ) | |
46 | ([[:punct:]]|\s|<|$) # trailing text |
|
62 | ([[:punct:]]|\s|<|$) # trailing text | |
47 | }x unless const_defined?(:AUTO_LINK_RE) |
|
63 | }x unless const_defined?(:AUTO_LINK_RE) | |
48 |
|
64 | |||
49 | # Turns all urls into clickable links (code from Rails). |
|
65 | # Turns all urls into clickable links (code from Rails). | |
50 | def inline_auto_link(text) |
|
66 | def inline_auto_link(text) | |
51 | text.gsub!(AUTO_LINK_RE) do |
|
67 | text.gsub!(AUTO_LINK_RE) do | |
52 | all, a, b, c, d = $&, $1, $2, $3, $4 |
|
68 | all, a, b, c, d = $&, $1, $2, $3, $4 | |
53 | if a =~ /<a\s/i || a =~ /![<>=]?/ |
|
69 | if a =~ /<a\s/i || a =~ /![<>=]?/ | |
54 | # don't replace URL's that are already linked |
|
70 | # don't replace URL's that are already linked | |
55 | # and URL's prefixed with ! !> !< != (textile images) |
|
71 | # and URL's prefixed with ! !> !< != (textile images) | |
56 | all |
|
72 | all | |
57 | else |
|
73 | else | |
58 | text = b + c |
|
74 | text = b + c | |
59 | %(#{a}<a href="#{b=="www."?"http://www.":b}#{c}">#{text}</a>#{d}) |
|
75 | %(#{a}<a href="#{b=="www."?"http://www.":b}#{c}">#{text}</a>#{d}) | |
60 | end |
|
76 | end | |
61 | end |
|
77 | end | |
62 | end |
|
78 | end | |
63 |
|
79 | |||
64 | # Turns all email addresses into clickable links (code from Rails). |
|
80 | # Turns all email addresses into clickable links (code from Rails). | |
65 | def inline_auto_mailto(text) |
|
81 | def inline_auto_mailto(text) | |
66 | text.gsub!(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do |
|
82 | text.gsub!(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do | |
67 | text = $1 |
|
83 | text = $1 | |
68 | %{<a href="mailto:#{$1}" class="email">#{text}</a>} |
|
84 | %{<a href="mailto:#{$1}" class="email">#{text}</a>} | |
69 | end |
|
85 | end | |
70 | end |
|
86 | end | |
71 | end |
|
87 | end | |
72 |
|
88 | |||
73 | public |
|
89 | public | |
74 |
|
90 | |||
75 | def self.to_html(text, options = {}) |
|
91 | def self.to_html(text, options = {}) | |
76 | TextileFormatter.new(text).to_html |
|
92 | TextileFormatter.new(text).to_html | |
77 | end |
|
93 | end | |
78 | end |
|
94 | end | |
79 | end |
|
95 | end |
@@ -1,123 +1,123 | |||||
1 |
|
1 | |||
2 | div.action_M { background: #fd8 } |
|
2 | div.action_M { background: #fd8 } | |
3 | div.action_D { background: #f88 } |
|
3 | div.action_D { background: #f88 } | |
4 | div.action_A { background: #bfb } |
|
4 | div.action_A { background: #bfb } | |
5 |
|
5 | |||
6 |
|
6 | |||
7 | tr.spacing { |
|
7 | tr.spacing { | |
8 | border: 1px solid #d7d7d7; |
|
8 | border: 1px solid #d7d7d7; | |
9 | } |
|
9 | } | |
10 |
|
10 | |||
11 | .line-num { |
|
11 | .line-num { | |
12 | border: 1px solid #d7d7d7; |
|
12 | border: 1px solid #d7d7d7; | |
13 | font-size: 0.8em; |
|
13 | font-size: 0.8em; | |
14 | text-align: right; |
|
14 | text-align: right; | |
15 | width: 3em; |
|
15 | width: 3em; | |
16 | padding-right: 3px; |
|
16 | padding-right: 3px; | |
17 | } |
|
17 | } | |
18 |
|
18 | |||
19 | .line-code { |
|
19 | .line-code { | |
20 | font-size: 1.4em; |
|
20 | font-size: 1.4em; | |
21 | } |
|
21 | } | |
22 |
|
22 | |||
23 | table.list thead th.list-filename { |
|
23 | table.list thead th.list-filename { | |
24 | background-color: #ddc; |
|
24 | background-color: #ddc; | |
25 | font-weight: bolder; |
|
25 | font-weight: bolder; | |
26 | text-align: left; |
|
26 | text-align: left; | |
27 | } |
|
27 | } | |
28 |
|
28 | |||
29 |
|
29 | |||
30 | /************* Coderay styles *************/ |
|
30 | /************* Coderay styles *************/ | |
31 |
|
31 | |||
32 | .CodeRay { |
|
32 | table.CodeRay { | |
33 | background-color: #fafafa; |
|
33 | background-color: #fafafa; | |
34 | } |
|
34 | } | |
35 | .CodeRay pre { margin: 0px } |
|
35 | .CodeRay pre { margin: 0px } | |
36 |
|
36 | |||
37 | span.CodeRay { white-space: pre; border: 0px; padding: 2px } |
|
37 | span.CodeRay { white-space: pre; border: 0px; padding: 2px } | |
38 |
|
38 | |||
39 | .CodeRay .no { padding: 0px 4px } |
|
39 | .CodeRay .no { padding: 0px 4px } | |
40 | .CodeRay .code { width: 100% } |
|
40 | .CodeRay .code { width: 100% } | |
41 |
|
41 | |||
42 | ol.CodeRay { font-size: 10pt } |
|
42 | ol.CodeRay { font-size: 10pt } | |
43 | ol.CodeRay li { white-space: pre } |
|
43 | ol.CodeRay li { white-space: pre } | |
44 |
|
44 | |||
45 | .CodeRay .code pre { overflow: auto } |
|
45 | .CodeRay .code pre { overflow: auto } | |
46 |
|
46 | |||
47 | .CodeRay .debug { color:white ! important; background:blue ! important; } |
|
47 | .CodeRay .debug { color:white ! important; background:blue ! important; } | |
48 |
|
48 | |||
49 | .CodeRay .af { color:#00C } |
|
49 | .CodeRay .af { color:#00C } | |
50 | .CodeRay .an { color:#007 } |
|
50 | .CodeRay .an { color:#007 } | |
51 | .CodeRay .av { color:#700 } |
|
51 | .CodeRay .av { color:#700 } | |
52 | .CodeRay .aw { color:#C00 } |
|
52 | .CodeRay .aw { color:#C00 } | |
53 | .CodeRay .bi { color:#509; font-weight:bold } |
|
53 | .CodeRay .bi { color:#509; font-weight:bold } | |
54 | .CodeRay .c { color:#666; } |
|
54 | .CodeRay .c { color:#666; } | |
55 |
|
55 | |||
56 | .CodeRay .ch { color:#04D } |
|
56 | .CodeRay .ch { color:#04D } | |
57 | .CodeRay .ch .k { color:#04D } |
|
57 | .CodeRay .ch .k { color:#04D } | |
58 | .CodeRay .ch .dl { color:#039 } |
|
58 | .CodeRay .ch .dl { color:#039 } | |
59 |
|
59 | |||
60 | .CodeRay .cl { color:#B06; font-weight:bold } |
|
60 | .CodeRay .cl { color:#B06; font-weight:bold } | |
61 | .CodeRay .co { color:#036; font-weight:bold } |
|
61 | .CodeRay .co { color:#036; font-weight:bold } | |
62 | .CodeRay .cr { color:#0A0 } |
|
62 | .CodeRay .cr { color:#0A0 } | |
63 | .CodeRay .cv { color:#369 } |
|
63 | .CodeRay .cv { color:#369 } | |
64 | .CodeRay .df { color:#099; font-weight:bold } |
|
64 | .CodeRay .df { color:#099; font-weight:bold } | |
65 | .CodeRay .di { color:#088; font-weight:bold } |
|
65 | .CodeRay .di { color:#088; font-weight:bold } | |
66 | .CodeRay .dl { color:black } |
|
66 | .CodeRay .dl { color:black } | |
67 | .CodeRay .do { color:#970 } |
|
67 | .CodeRay .do { color:#970 } | |
68 | .CodeRay .ds { color:#D42; font-weight:bold } |
|
68 | .CodeRay .ds { color:#D42; font-weight:bold } | |
69 | .CodeRay .e { color:#666; font-weight:bold } |
|
69 | .CodeRay .e { color:#666; font-weight:bold } | |
70 | .CodeRay .en { color:#800; font-weight:bold } |
|
70 | .CodeRay .en { color:#800; font-weight:bold } | |
71 | .CodeRay .er { color:#F00; background-color:#FAA } |
|
71 | .CodeRay .er { color:#F00; background-color:#FAA } | |
72 | .CodeRay .ex { color:#F00; font-weight:bold } |
|
72 | .CodeRay .ex { color:#F00; font-weight:bold } | |
73 | .CodeRay .fl { color:#60E; font-weight:bold } |
|
73 | .CodeRay .fl { color:#60E; font-weight:bold } | |
74 | .CodeRay .fu { color:#06B; font-weight:bold } |
|
74 | .CodeRay .fu { color:#06B; font-weight:bold } | |
75 | .CodeRay .gv { color:#d70; font-weight:bold } |
|
75 | .CodeRay .gv { color:#d70; font-weight:bold } | |
76 | .CodeRay .hx { color:#058; font-weight:bold } |
|
76 | .CodeRay .hx { color:#058; font-weight:bold } | |
77 | .CodeRay .i { color:#00D; font-weight:bold } |
|
77 | .CodeRay .i { color:#00D; font-weight:bold } | |
78 | .CodeRay .ic { color:#B44; font-weight:bold } |
|
78 | .CodeRay .ic { color:#B44; font-weight:bold } | |
79 |
|
79 | |||
80 | .CodeRay .il { background: #eee } |
|
80 | .CodeRay .il { background: #eee } | |
81 | .CodeRay .il .il { background: #ddd } |
|
81 | .CodeRay .il .il { background: #ddd } | |
82 | .CodeRay .il .il .il { background: #ccc } |
|
82 | .CodeRay .il .il .il { background: #ccc } | |
83 | .CodeRay .il .idl { font-weight: bold; color: #888 } |
|
83 | .CodeRay .il .idl { font-weight: bold; color: #888 } | |
84 |
|
84 | |||
85 | .CodeRay .in { color:#B2B; font-weight:bold } |
|
85 | .CodeRay .in { color:#B2B; font-weight:bold } | |
86 | .CodeRay .iv { color:#33B } |
|
86 | .CodeRay .iv { color:#33B } | |
87 | .CodeRay .la { color:#970; font-weight:bold } |
|
87 | .CodeRay .la { color:#970; font-weight:bold } | |
88 | .CodeRay .lv { color:#963 } |
|
88 | .CodeRay .lv { color:#963 } | |
89 | .CodeRay .oc { color:#40E; font-weight:bold } |
|
89 | .CodeRay .oc { color:#40E; font-weight:bold } | |
90 | .CodeRay .of { color:#000; font-weight:bold } |
|
90 | .CodeRay .of { color:#000; font-weight:bold } | |
91 | .CodeRay .op { } |
|
91 | .CodeRay .op { } | |
92 | .CodeRay .pc { color:#038; font-weight:bold } |
|
92 | .CodeRay .pc { color:#038; font-weight:bold } | |
93 | .CodeRay .pd { color:#369; font-weight:bold } |
|
93 | .CodeRay .pd { color:#369; font-weight:bold } | |
94 | .CodeRay .pp { color:#579 } |
|
94 | .CodeRay .pp { color:#579 } | |
95 | .CodeRay .pt { color:#339; font-weight:bold } |
|
95 | .CodeRay .pt { color:#339; font-weight:bold } | |
96 | .CodeRay .r { color:#080; font-weight:bold } |
|
96 | .CodeRay .r { color:#080; font-weight:bold } | |
97 |
|
97 | |||
98 | .CodeRay .rx { background-color:#fff0ff } |
|
98 | .CodeRay .rx { background-color:#fff0ff } | |
99 | .CodeRay .rx .k { color:#808 } |
|
99 | .CodeRay .rx .k { color:#808 } | |
100 | .CodeRay .rx .dl { color:#404 } |
|
100 | .CodeRay .rx .dl { color:#404 } | |
101 | .CodeRay .rx .mod { color:#C2C } |
|
101 | .CodeRay .rx .mod { color:#C2C } | |
102 | .CodeRay .rx .fu { color:#404; font-weight: bold } |
|
102 | .CodeRay .rx .fu { color:#404; font-weight: bold } | |
103 |
|
103 | |||
104 | .CodeRay .s { background-color:#fff0f0 } |
|
104 | .CodeRay .s { background-color:#fff0f0 } | |
105 | .CodeRay .s .s { background-color:#ffe0e0 } |
|
105 | .CodeRay .s .s { background-color:#ffe0e0 } | |
106 | .CodeRay .s .s .s { background-color:#ffd0d0 } |
|
106 | .CodeRay .s .s .s { background-color:#ffd0d0 } | |
107 | .CodeRay .s .k { color:#D20 } |
|
107 | .CodeRay .s .k { color:#D20 } | |
108 | .CodeRay .s .dl { color:#710 } |
|
108 | .CodeRay .s .dl { color:#710 } | |
109 |
|
109 | |||
110 | .CodeRay .sh { background-color:#f0fff0 } |
|
110 | .CodeRay .sh { background-color:#f0fff0 } | |
111 | .CodeRay .sh .k { color:#2B2 } |
|
111 | .CodeRay .sh .k { color:#2B2 } | |
112 | .CodeRay .sh .dl { color:#161 } |
|
112 | .CodeRay .sh .dl { color:#161 } | |
113 |
|
113 | |||
114 | .CodeRay .sy { color:#A60 } |
|
114 | .CodeRay .sy { color:#A60 } | |
115 | .CodeRay .sy .k { color:#A60 } |
|
115 | .CodeRay .sy .k { color:#A60 } | |
116 | .CodeRay .sy .dl { color:#630 } |
|
116 | .CodeRay .sy .dl { color:#630 } | |
117 |
|
117 | |||
118 | .CodeRay .ta { color:#070 } |
|
118 | .CodeRay .ta { color:#070 } | |
119 | .CodeRay .tf { color:#070; font-weight:bold } |
|
119 | .CodeRay .tf { color:#070; font-weight:bold } | |
120 | .CodeRay .ts { color:#D70; font-weight:bold } |
|
120 | .CodeRay .ts { color:#D70; font-weight:bold } | |
121 | .CodeRay .ty { color:#339; font-weight:bold } |
|
121 | .CodeRay .ty { color:#339; font-weight:bold } | |
122 | .CodeRay .v { color:#036 } |
|
122 | .CodeRay .v { color:#036 } | |
123 | .CodeRay .xt { color:#444 } |
|
123 | .CodeRay .xt { color:#444 } |
@@ -1,262 +1,268 | |||||
1 | require "set" |
|
1 | require "set" | |
2 |
|
2 | |||
3 | module CodeRay |
|
3 | module CodeRay | |
4 | module Encoders |
|
4 | module Encoders | |
5 |
|
5 | |||
6 | # = HTML Encoder |
|
6 | # = HTML Encoder | |
7 | # |
|
7 | # | |
8 | # This is CodeRay's most important highlighter: |
|
8 | # This is CodeRay's most important highlighter: | |
9 | # It provides save, fast XHTML generation and CSS support. |
|
9 | # It provides save, fast XHTML generation and CSS support. | |
10 | # |
|
10 | # | |
11 | # == Usage |
|
11 | # == Usage | |
12 | # |
|
12 | # | |
13 | # require 'coderay' |
|
13 | # require 'coderay' | |
14 | # puts CodeRay.scan('Some /code/', :ruby).html #-> a HTML page |
|
14 | # puts CodeRay.scan('Some /code/', :ruby).html #-> a HTML page | |
15 | # puts CodeRay.scan('Some /code/', :ruby).html(:wrap => :span) |
|
15 | # puts CodeRay.scan('Some /code/', :ruby).html(:wrap => :span) | |
16 | # #-> <span class="CodeRay"><span class="co">Some</span> /code/</span> |
|
16 | # #-> <span class="CodeRay"><span class="co">Some</span> /code/</span> | |
17 | # puts CodeRay.scan('Some /code/', :ruby).span #-> the same |
|
17 | # puts CodeRay.scan('Some /code/', :ruby).span #-> the same | |
18 | # |
|
18 | # | |
19 | # puts CodeRay.scan('Some code', :ruby).html( |
|
19 | # puts CodeRay.scan('Some code', :ruby).html( | |
20 | # :wrap => nil, |
|
20 | # :wrap => nil, | |
21 | # :line_numbers => :inline, |
|
21 | # :line_numbers => :inline, | |
22 | # :css => :style |
|
22 | # :css => :style | |
23 | # ) |
|
23 | # ) | |
24 | # #-> <span class="no">1</span> <span style="color:#036; font-weight:bold;">Some</span> code |
|
24 | # #-> <span class="no">1</span> <span style="color:#036; font-weight:bold;">Some</span> code | |
25 | # |
|
25 | # | |
26 | # == Options |
|
26 | # == Options | |
27 | # |
|
27 | # | |
|
28 | # === :escape | |||
|
29 | # Escape html entities | |||
|
30 | # Default: true | |||
|
31 | # | |||
28 | # === :tab_width |
|
32 | # === :tab_width | |
29 | # Convert \t characters to +n+ spaces (a number.) |
|
33 | # Convert \t characters to +n+ spaces (a number.) | |
30 | # Default: 8 |
|
34 | # Default: 8 | |
31 | # |
|
35 | # | |
32 | # === :css |
|
36 | # === :css | |
33 | # How to include the styles; can be :class or :style. |
|
37 | # How to include the styles; can be :class or :style. | |
34 | # |
|
38 | # | |
35 | # Default: :class |
|
39 | # Default: :class | |
36 | # |
|
40 | # | |
37 | # === :wrap |
|
41 | # === :wrap | |
38 | # Wrap in :page, :div, :span or nil. |
|
42 | # Wrap in :page, :div, :span or nil. | |
39 | # |
|
43 | # | |
40 | # You can also use Encoders::Div and Encoders::Span. |
|
44 | # You can also use Encoders::Div and Encoders::Span. | |
41 | # |
|
45 | # | |
42 | # Default: nil |
|
46 | # Default: nil | |
43 | # |
|
47 | # | |
44 | # === :line_numbers |
|
48 | # === :line_numbers | |
45 | # Include line numbers in :table, :inline, :list or nil (no line numbers) |
|
49 | # Include line numbers in :table, :inline, :list or nil (no line numbers) | |
46 | # |
|
50 | # | |
47 | # Default: nil |
|
51 | # Default: nil | |
48 | # |
|
52 | # | |
49 | # === :line_number_start |
|
53 | # === :line_number_start | |
50 | # Where to start with line number counting. |
|
54 | # Where to start with line number counting. | |
51 | # |
|
55 | # | |
52 | # Default: 1 |
|
56 | # Default: 1 | |
53 | # |
|
57 | # | |
54 | # === :bold_every |
|
58 | # === :bold_every | |
55 | # Make every +n+-th number appear bold. |
|
59 | # Make every +n+-th number appear bold. | |
56 | # |
|
60 | # | |
57 | # Default: 10 |
|
61 | # Default: 10 | |
58 | # |
|
62 | # | |
59 | # === :hint |
|
63 | # === :hint | |
60 | # Include some information into the output using the title attribute. |
|
64 | # Include some information into the output using the title attribute. | |
61 | # Can be :info (show token type on mouse-over), :info_long (with full path) |
|
65 | # Can be :info (show token type on mouse-over), :info_long (with full path) | |
62 | # or :debug (via inspect). |
|
66 | # or :debug (via inspect). | |
63 | # |
|
67 | # | |
64 | # Default: false |
|
68 | # Default: false | |
65 | class HTML < Encoder |
|
69 | class HTML < Encoder | |
66 |
|
70 | |||
67 | include Streamable |
|
71 | include Streamable | |
68 | register_for :html |
|
72 | register_for :html | |
69 |
|
73 | |||
70 | FILE_EXTENSION = 'html' |
|
74 | FILE_EXTENSION = 'html' | |
71 |
|
75 | |||
72 | DEFAULT_OPTIONS = { |
|
76 | DEFAULT_OPTIONS = { | |
|
77 | :escape => true, | |||
73 | :tab_width => 8, |
|
78 | :tab_width => 8, | |
74 |
|
79 | |||
75 | :level => :xhtml, |
|
80 | :level => :xhtml, | |
76 | :css => :class, |
|
81 | :css => :class, | |
77 |
|
82 | |||
78 | :style => :cycnus, |
|
83 | :style => :cycnus, | |
79 |
|
84 | |||
80 | :wrap => nil, |
|
85 | :wrap => nil, | |
81 |
|
86 | |||
82 | :line_numbers => nil, |
|
87 | :line_numbers => nil, | |
83 | :line_number_start => 1, |
|
88 | :line_number_start => 1, | |
84 | :bold_every => 10, |
|
89 | :bold_every => 10, | |
85 |
|
90 | |||
86 | :hint => false, |
|
91 | :hint => false, | |
87 | } |
|
92 | } | |
88 |
|
93 | |||
89 | helper :output, :css |
|
94 | helper :output, :css | |
90 |
|
95 | |||
91 | attr_reader :css |
|
96 | attr_reader :css | |
92 |
|
97 | |||
93 | protected |
|
98 | protected | |
94 |
|
99 | |||
95 | HTML_ESCAPE = { #:nodoc: |
|
100 | HTML_ESCAPE = { #:nodoc: | |
96 | '&' => '&', |
|
101 | '&' => '&', | |
97 | '"' => '"', |
|
102 | '"' => '"', | |
98 | '>' => '>', |
|
103 | '>' => '>', | |
99 | '<' => '<', |
|
104 | '<' => '<', | |
100 | } |
|
105 | } | |
101 |
|
106 | |||
102 | # This was to prevent illegal HTML. |
|
107 | # This was to prevent illegal HTML. | |
103 | # Strange chars should still be avoided in codes. |
|
108 | # Strange chars should still be avoided in codes. | |
104 | evil_chars = Array(0x00...0x20) - [?\n, ?\t, ?\s] |
|
109 | evil_chars = Array(0x00...0x20) - [?\n, ?\t, ?\s] | |
105 | evil_chars.each { |i| HTML_ESCAPE[i.chr] = ' ' } |
|
110 | evil_chars.each { |i| HTML_ESCAPE[i.chr] = ' ' } | |
106 | #ansi_chars = Array(0x7f..0xff) |
|
111 | #ansi_chars = Array(0x7f..0xff) | |
107 | #ansi_chars.each { |i| HTML_ESCAPE[i.chr] = '&#%d;' % i } |
|
112 | #ansi_chars.each { |i| HTML_ESCAPE[i.chr] = '&#%d;' % i } | |
108 | # \x9 (\t) and \xA (\n) not included |
|
113 | # \x9 (\t) and \xA (\n) not included | |
109 | #HTML_ESCAPE_PATTERN = /[\t&"><\0-\x8\xB-\x1f\x7f-\xff]/ |
|
114 | #HTML_ESCAPE_PATTERN = /[\t&"><\0-\x8\xB-\x1f\x7f-\xff]/ | |
110 | HTML_ESCAPE_PATTERN = /[\t"&><\0-\x8\xB-\x1f]/ |
|
115 | HTML_ESCAPE_PATTERN = /[\t"&><\0-\x8\xB-\x1f]/ | |
111 |
|
116 | |||
112 | TOKEN_KIND_TO_INFO = Hash.new { |h, kind| |
|
117 | TOKEN_KIND_TO_INFO = Hash.new { |h, kind| | |
113 | h[kind] = |
|
118 | h[kind] = | |
114 | case kind |
|
119 | case kind | |
115 | when :pre_constant |
|
120 | when :pre_constant | |
116 | 'Predefined constant' |
|
121 | 'Predefined constant' | |
117 | else |
|
122 | else | |
118 | kind.to_s.gsub(/_/, ' ').gsub(/\b\w/) { $&.capitalize } |
|
123 | kind.to_s.gsub(/_/, ' ').gsub(/\b\w/) { $&.capitalize } | |
119 | end |
|
124 | end | |
120 | } |
|
125 | } | |
121 |
|
126 | |||
122 | TRANSPARENT_TOKEN_KINDS = [ |
|
127 | TRANSPARENT_TOKEN_KINDS = [ | |
123 | :delimiter, :modifier, :content, :escape, :inline_delimiter, |
|
128 | :delimiter, :modifier, :content, :escape, :inline_delimiter, | |
124 | ].to_set |
|
129 | ].to_set | |
125 |
|
130 | |||
126 | # Generate a hint about the given +classes+ in a +hint+ style. |
|
131 | # Generate a hint about the given +classes+ in a +hint+ style. | |
127 | # |
|
132 | # | |
128 | # +hint+ may be :info, :info_long or :debug. |
|
133 | # +hint+ may be :info, :info_long or :debug. | |
129 | def self.token_path_to_hint hint, classes |
|
134 | def self.token_path_to_hint hint, classes | |
130 | title = |
|
135 | title = | |
131 | case hint |
|
136 | case hint | |
132 | when :info |
|
137 | when :info | |
133 | TOKEN_KIND_TO_INFO[classes.first] |
|
138 | TOKEN_KIND_TO_INFO[classes.first] | |
134 | when :info_long |
|
139 | when :info_long | |
135 | classes.reverse.map { |kind| TOKEN_KIND_TO_INFO[kind] }.join('/') |
|
140 | classes.reverse.map { |kind| TOKEN_KIND_TO_INFO[kind] }.join('/') | |
136 | when :debug |
|
141 | when :debug | |
137 | classes.inspect |
|
142 | classes.inspect | |
138 | end |
|
143 | end | |
139 | " title=\"#{title}\"" |
|
144 | " title=\"#{title}\"" | |
140 | end |
|
145 | end | |
141 |
|
146 | |||
142 | def setup options |
|
147 | def setup options | |
143 | super |
|
148 | super | |
144 |
|
149 | |||
145 | @HTML_ESCAPE = HTML_ESCAPE.dup |
|
150 | @HTML_ESCAPE = HTML_ESCAPE.dup | |
146 | @HTML_ESCAPE["\t"] = ' ' * options[:tab_width] |
|
151 | @HTML_ESCAPE["\t"] = ' ' * options[:tab_width] | |
147 |
|
152 | |||
|
153 | @escape = options[:escape] | |||
148 | @opened = [nil] |
|
154 | @opened = [nil] | |
149 | @css = CSS.new options[:style] |
|
155 | @css = CSS.new options[:style] | |
150 |
|
156 | |||
151 | hint = options[:hint] |
|
157 | hint = options[:hint] | |
152 | if hint and not [:debug, :info, :info_long].include? hint |
|
158 | if hint and not [:debug, :info, :info_long].include? hint | |
153 | raise ArgumentError, "Unknown value %p for :hint; \ |
|
159 | raise ArgumentError, "Unknown value %p for :hint; \ | |
154 | expected :info, :debug, false, or nil." % hint |
|
160 | expected :info, :debug, false, or nil." % hint | |
155 | end |
|
161 | end | |
156 |
|
162 | |||
157 | case options[:css] |
|
163 | case options[:css] | |
158 |
|
164 | |||
159 | when :class |
|
165 | when :class | |
160 | @css_style = Hash.new do |h, k| |
|
166 | @css_style = Hash.new do |h, k| | |
161 | c = Tokens::ClassOfKind[k.first] |
|
167 | c = Tokens::ClassOfKind[k.first] | |
162 | if c == :NO_HIGHLIGHT and not hint |
|
168 | if c == :NO_HIGHLIGHT and not hint | |
163 | h[k.dup] = false |
|
169 | h[k.dup] = false | |
164 | else |
|
170 | else | |
165 | title = if hint |
|
171 | title = if hint | |
166 | HTML.token_path_to_hint(hint, k[1..-1] << k.first) |
|
172 | HTML.token_path_to_hint(hint, k[1..-1] << k.first) | |
167 | else |
|
173 | else | |
168 | '' |
|
174 | '' | |
169 | end |
|
175 | end | |
170 | if c == :NO_HIGHLIGHT |
|
176 | if c == :NO_HIGHLIGHT | |
171 | h[k.dup] = '<span%s>' % [title] |
|
177 | h[k.dup] = '<span%s>' % [title] | |
172 | else |
|
178 | else | |
173 | h[k.dup] = '<span%s class="%s">' % [title, c] |
|
179 | h[k.dup] = '<span%s class="%s">' % [title, c] | |
174 | end |
|
180 | end | |
175 | end |
|
181 | end | |
176 | end |
|
182 | end | |
177 |
|
183 | |||
178 | when :style |
|
184 | when :style | |
179 | @css_style = Hash.new do |h, k| |
|
185 | @css_style = Hash.new do |h, k| | |
180 | if k.is_a? ::Array |
|
186 | if k.is_a? ::Array | |
181 | styles = k.dup |
|
187 | styles = k.dup | |
182 | else |
|
188 | else | |
183 | styles = [k] |
|
189 | styles = [k] | |
184 | end |
|
190 | end | |
185 | type = styles.first |
|
191 | type = styles.first | |
186 | classes = styles.map { |c| Tokens::ClassOfKind[c] } |
|
192 | classes = styles.map { |c| Tokens::ClassOfKind[c] } | |
187 | if classes.first == :NO_HIGHLIGHT and not hint |
|
193 | if classes.first == :NO_HIGHLIGHT and not hint | |
188 | h[k] = false |
|
194 | h[k] = false | |
189 | else |
|
195 | else | |
190 | styles.shift if TRANSPARENT_TOKEN_KINDS.include? styles.first |
|
196 | styles.shift if TRANSPARENT_TOKEN_KINDS.include? styles.first | |
191 | title = HTML.token_path_to_hint hint, styles |
|
197 | title = HTML.token_path_to_hint hint, styles | |
192 | style = @css[*classes] |
|
198 | style = @css[*classes] | |
193 | h[k] = |
|
199 | h[k] = | |
194 | if style |
|
200 | if style | |
195 | '<span%s style="%s">' % [title, style] |
|
201 | '<span%s style="%s">' % [title, style] | |
196 | else |
|
202 | else | |
197 | false |
|
203 | false | |
198 | end |
|
204 | end | |
199 | end |
|
205 | end | |
200 | end |
|
206 | end | |
201 |
|
207 | |||
202 | else |
|
208 | else | |
203 | raise ArgumentError, "Unknown value %p for :css." % options[:css] |
|
209 | raise ArgumentError, "Unknown value %p for :css." % options[:css] | |
204 |
|
210 | |||
205 | end |
|
211 | end | |
206 | end |
|
212 | end | |
207 |
|
213 | |||
208 | def finish options |
|
214 | def finish options | |
209 | not_needed = @opened.shift |
|
215 | not_needed = @opened.shift | |
210 | @out << '</span>' * @opened.size |
|
216 | @out << '</span>' * @opened.size | |
211 | unless @opened.empty? |
|
217 | unless @opened.empty? | |
212 | warn '%d tokens still open: %p' % [@opened.size, @opened] |
|
218 | warn '%d tokens still open: %p' % [@opened.size, @opened] | |
213 | end |
|
219 | end | |
214 |
|
220 | |||
215 | @out.extend Output |
|
221 | @out.extend Output | |
216 | @out.css = @css |
|
222 | @out.css = @css | |
217 | @out.numerize! options[:line_numbers], options |
|
223 | @out.numerize! options[:line_numbers], options | |
218 | @out.wrap! options[:wrap] |
|
224 | @out.wrap! options[:wrap] | |
219 |
|
225 | |||
220 | super |
|
226 | super | |
221 | end |
|
227 | end | |
222 |
|
228 | |||
223 | def token text, type |
|
229 | def token text, type | |
224 | if text.is_a? ::String |
|
230 | if text.is_a? ::String | |
225 | if text =~ /#{HTML_ESCAPE_PATTERN}/o |
|
231 | if @escape && (text =~ /#{HTML_ESCAPE_PATTERN}/o) | |
226 | text = text.gsub(/#{HTML_ESCAPE_PATTERN}/o) { |m| @HTML_ESCAPE[m] } |
|
232 | text = text.gsub(/#{HTML_ESCAPE_PATTERN}/o) { |m| @HTML_ESCAPE[m] } | |
227 | end |
|
233 | end | |
228 | @opened[0] = type |
|
234 | @opened[0] = type | |
229 | if style = @css_style[@opened] |
|
235 | if style = @css_style[@opened] | |
230 | @out << style << text << '</span>' |
|
236 | @out << style << text << '</span>' | |
231 | else |
|
237 | else | |
232 | @out << text |
|
238 | @out << text | |
233 | end |
|
239 | end | |
234 | else |
|
240 | else | |
235 | case text |
|
241 | case text | |
236 | when :open |
|
242 | when :open | |
237 | @opened[0] = type |
|
243 | @opened[0] = type | |
238 | @out << (@css_style[@opened] || '<span>') |
|
244 | @out << (@css_style[@opened] || '<span>') | |
239 | @opened << type |
|
245 | @opened << type | |
240 | when :close |
|
246 | when :close | |
241 | if @opened.empty? |
|
247 | if @opened.empty? | |
242 | # nothing to close |
|
248 | # nothing to close | |
243 | else |
|
249 | else | |
244 | if $DEBUG and (@opened.size == 1 or @opened.last != type) |
|
250 | if $DEBUG and (@opened.size == 1 or @opened.last != type) | |
245 | raise 'Malformed token stream: Trying to close a token (%p) \ |
|
251 | raise 'Malformed token stream: Trying to close a token (%p) \ | |
246 | that is not open. Open are: %p.' % [type, @opened[1..-1]] |
|
252 | that is not open. Open are: %p.' % [type, @opened[1..-1]] | |
247 | end |
|
253 | end | |
248 | @out << '</span>' |
|
254 | @out << '</span>' | |
249 | @opened.pop |
|
255 | @opened.pop | |
250 | end |
|
256 | end | |
251 | when nil |
|
257 | when nil | |
252 | raise 'Token with nil as text was given: %p' % [[text, type]] |
|
258 | raise 'Token with nil as text was given: %p' % [[text, type]] | |
253 | else |
|
259 | else | |
254 | raise 'unknown token kind: %p' % text |
|
260 | raise 'unknown token kind: %p' % text | |
255 | end |
|
261 | end | |
256 | end |
|
262 | end | |
257 | end |
|
263 | end | |
258 |
|
264 | |||
259 | end |
|
265 | end | |
260 |
|
266 | |||
261 | end |
|
267 | end | |
262 | end |
|
268 | end |
General Comments 0
You need to be logged in to leave comments.
Login now