@page.content = WikiContent.new(:page => @page) if @page.new_record?
@content = @page.content_for_version(params[:version])
- @content.text = "h1. #{@page.pretty_title}" if @content.text.blank?
+ @content.text = initial_page_content(@page) if @content.text.blank?
# don't keep previous comment
@content.comments = nil
if request.get?
def editable?(page = @page)
page.editable_by?(User.current)
end
+
+ # Returns the default content of a new wiki page
+ def initial_page_content(page)
+ helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
+ extend helper unless self.instance_of?(helper)
+ helper.instance_method(:initial_page_content).bind(self).call(page)
+ end
end
require 'coderay'
require 'coderay/helpers/file_type'
+require 'forwardable'
module ApplicationHelper
include Redmine::WikiFormatting::Macros::Definitions
+ extend Forwardable
+ def_delegators :wiki_helper, :wikitoolbar_for, :heads_for_wiki_formatter
+
def current_role
@current_role ||= User.current.role_for_project(@project)
end
end
end
- text = (Setting.text_formatting == 'textile') ?
- Redmine::WikiFormatting.to_html(text) { |macro, args| exec_macro(macro, obj, args) } :
- simple_format(auto_link(h(text)))
+ text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text) { |macro, args| exec_macro(macro, obj, args) }
# different methods for formatting wiki links
case options[:wiki_links]
end
end
- def wikitoolbar_for(field_id)
- return '' unless Setting.text_formatting == 'textile'
-
- help_link = l(:setting_text_formatting) + ': ' +
- link_to(l(:label_help), compute_public_path('wiki_syntax', 'help', 'html'),
- :onclick => "window.open(\"#{ compute_public_path('wiki_syntax', 'help', 'html') }\", \"\", \"resizable=yes, location=no, width=300, height=640, menubar=no, status=no, scrollbars=yes\"); return false;")
-
- javascript_include_tag('jstoolbar/jstoolbar') +
- javascript_include_tag("jstoolbar/lang/jstoolbar-#{current_language}") +
- javascript_tag("var toolbar = new jsToolBar($('#{field_id}')); toolbar.setHelpLink('#{help_link}'); toolbar.draw();")
- end
-
def content_for(name, content = nil, &block)
@has_content ||= {}
@has_content[name] = true
def has_content?(name)
(@has_content && @has_content[name]) || false
end
+
+ private
+
+ def wiki_helper
+ helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
+ extend helper
+ return self
+ end
end
<meta name="keywords" content="issue,bug,tracker" />
<%= stylesheet_link_tag 'application', :media => 'all' %>
<%= javascript_include_tag :defaults %>
-<%= stylesheet_link_tag 'jstoolbar' %>
+<%= heads_for_wiki_formatter %>
<!--[if IE]>
<style type="text/css">
* html body{ width: expression( document.documentElement.clientWidth < 900 ? '900px' : '100%' ); }
<body>
<%= yield %>
<hr />
-<span class="footer"><%= Redmine::WikiFormatting.to_html(Setting.emails_footer) %></span>
+<span class="footer"><%= Redmine::WikiFormatting.to_html(Setting.text_formatting, Setting.emails_footer) %></span>
</body>
</html>
<%= select_tag 'settings[protocol]', options_for_select(['http', 'https'], Setting.protocol) %></p>
<p><label><%= l(:setting_text_formatting) %></label>
-<%= select_tag 'settings[text_formatting]', options_for_select([[l(:label_none), "0"], ["textile", "textile"]], Setting.text_formatting) %></p>
+<%= select_tag 'settings[text_formatting]', options_for_select([[l(:label_none), "0"], *Redmine::WikiFormatting.format_names.collect{|name| [name, name]} ], Setting.text_formatting.to_sym) %></p>
<p><label><%= l(:setting_wiki_compression) %></label>
<%= select_tag 'settings[wiki_compression]', options_for_select( [[l(:label_none), 0], ["gzip", "gzip"]], Setting.wiki_compression) %></p>
require 'redmine/themes'
require 'redmine/hook'
require 'redmine/plugin'
+require 'redmine/wiki_formatting'
begin
require_library_or_gem 'RMagick' unless Object.const_defined?(:Magick)
activity.register :wiki_edits, :class_name => 'WikiContent::Version', :default => false
activity.register :messages, :default => false
end
+
+Redmine::WikiFormatting.map do |format|
+ format.register :textile, Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting::Textile::Helper
+end
def activity_provider(*args)
Redmine::Activity.register(*args)
end
+
+ # Registers a wiki formatter.
+ #
+ # Parameters:
+ # * +name+ - human-readable name
+ # * +formatter+ - formatter class, which should have an instance method +to_html+
+ # * +helper+ - helper module, which will be included by wiki pages
+ def wiki_format_provider(name, formatter, helper)
+ Redmine::WikiFormatting.register(name, formatter, helper)
+ end
# Returns +true+ if the plugin can be configured.
def configurable?
-# redMine - project management software
-# Copyright (C) 2006-2007 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2008 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-require 'redcloth3'
-require 'coderay'
-
module Redmine
module WikiFormatting
-
- private
-
- class TextileFormatter < RedCloth3
-
- # auto_link rule after textile rules so that it doesn't break !image_url! tags
- RULES = [:textile, :block_markdown_rule, :inline_auto_link, :inline_auto_mailto, :inline_toc, :inline_macros]
+ @@formatters = {}
+
+ class << self
+ def map
+ yield self
+ end
- def initialize(*args)
- super
- self.hard_breaks=true
- self.no_span_caps=true
+ def register(name, formatter, helper)
+ raise ArgumentError, "format name '#{name}' is already taken" if @@formatters[name]
+ @@formatters[name.to_sym] = {:formatter => formatter, :helper => helper}
end
- def to_html(*rules, &block)
- @toc = []
- @macros_runner = block
- super(*RULES).to_s
+ def formatter_for(name)
+ entry = @@formatters[name.to_sym]
+ (entry && entry[:formatter]) || Redmine::WikiFormatting::NullFormatter::Formatter
end
-
- private
-
- # Patch for RedCloth. Fixed in RedCloth r128 but _why hasn't released it yet.
- # <a href="http://code.whytheluckystiff.net/redcloth/changeset/128">http://code.whytheluckystiff.net/redcloth/changeset/128</a>
- def hard_break( text )
- text.gsub!( /(.)\n(?!\n|\Z|>| *(>? *[#*=]+(\s|$)|[{|]))/, "\\1<br />\n" ) if hard_breaks
+
+ def helper_for(name)
+ entry = @@formatters[name.to_sym]
+ (entry && entry[:helper]) || Redmine::WikiFormatting::NullFormatter::Helper
end
- # Patch to add code highlighting support to RedCloth
- def smooth_offtags( text )
- unless @pre_list.empty?
- ## replace <pre> content
- text.gsub!(/<redpre#(\d+)>/) do
- content = @pre_list[$1.to_i]
- if content.match(/<code\s+class="(\w+)">\s?(.+)/m)
- content = "<code class=\"#{$1} CodeRay\">" +
- CodeRay.scan($2, $1.downcase).html(:escape => false, :line_numbers => :inline)
- end
- content
- end
- end
+ def format_names
+ @@formatters.keys.map
end
- # Patch to add 'table of content' support to RedCloth
- def textile_p_withtoc(tag, atts, cite, content)
- # removes wiki links from the item
- toc_item = content.gsub(/(\[\[|\]\])/, '')
- # removes styles
- # eg. %{color:red}Triggers% => Triggers
- toc_item.gsub! %r[%\{[^\}]*\}([^%]+)%], '\\1'
+ def to_html(format, text, options = {}, &block)
+ formatter_for(format).new(text).to_html(&block)
+ end
+ end
+
+ # Default formatter module
+ module NullFormatter
+ class Formatter
+ include ActionView::Helpers::TagHelper
+ include ActionView::Helpers::TextHelper
- # replaces non word caracters by dashes
- anchor = toc_item.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-')
-
- unless anchor.blank?
- if tag =~ /^h(\d)$/
- @toc << [$1.to_i, anchor, toc_item]
- end
- atts << " id=\"#{anchor}\""
- content = content + "<a href=\"##{anchor}\" class=\"wiki-anchor\">¶</a>"
+ def initialize(text)
+ @text = text
end
- textile_p(tag, atts, cite, content)
- end
-
- alias :textile_h1 :textile_p_withtoc
- alias :textile_h2 :textile_p_withtoc
- alias :textile_h3 :textile_p_withtoc
-
- def inline_toc(text)
- text.gsub!(/<p>\{\{([<>]?)toc\}\}<\/p>/i) do
- div_class = 'toc'
- div_class << ' right' if $1 == '>'
- div_class << ' left' if $1 == '<'
- out = "<ul class=\"#{div_class}\">"
- @toc.each do |heading|
- level, anchor, toc_item = heading
- out << "<li class=\"heading#{level}\"><a href=\"##{anchor}\">#{toc_item}</a></li>\n"
- end
- out << '</ul>'
- out
+
+ def to_html(*args)
+ simple_format(auto_link(CGI::escapeHTML(@text)))
end
end
- MACROS_RE = /
- (!)? # escaping
- (
- \{\{ # opening tag
- ([\w]+) # macro name
- (\(([^\}]*)\))? # optional arguments
- \}\} # closing tag
- )
- /x unless const_defined?(:MACROS_RE)
-
- def inline_macros(text)
- text.gsub!(MACROS_RE) do
- esc, all, macro = $1, $2, $3.downcase
- args = ($5 || '').split(',').each(&:strip)
- if esc.nil?
- begin
- @macros_runner.call(macro, args)
- rescue => e
- "<div class=\"flash error\">Error executing the <strong>#{macro}</strong> macro (#{e})</div>"
- end || all
- else
- all
- end
+ module Helper
+ def wikitoolbar_for(field_id)
end
- end
- AUTO_LINK_RE = %r{
- ( # leading text
- <\w+.*?>| # leading HTML tag, or
- [^=<>!:'"/]| # leading punctuation, or
- ^ # beginning of line
- )
- (
- (?:https?://)| # protocol spec, or
- (?:ftp://)|
- (?:www\.) # www.*
- )
- (
- (\S+?) # url
- (\/)? # slash
- )
- ([^\w\=\/;\(\)]*?) # post
- (?=<|\s|$)
- }x unless const_defined?(:AUTO_LINK_RE)
-
- # Turns all urls into clickable links (code from Rails).
- def inline_auto_link(text)
- text.gsub!(AUTO_LINK_RE) do
- all, leading, proto, url, post = $&, $1, $2, $3, $6
- if leading =~ /<a\s/i || leading =~ /![<>=]?/
- # don't replace URL's that are already linked
- # and URL's prefixed with ! !> !< != (textile images)
- all
- else
- # 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
- %(#{leading}<a class="external" href="#{proto=="www."?"http://www.":proto}#{url}">#{proto + url}</a>#{post})
- end
+ def heads_for_wiki_formatter
end
- end
-
- # Turns all email addresses into clickable links (code from Rails).
- def inline_auto_mailto(text)
- text.gsub!(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do
- mail = $1
- if text.match(/<a\b[^>]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/)
- mail
- else
- %{<a href="mailto:#{mail}" class="email">#{mail}</a>}
- end
+
+ def initial_page_content(page)
+ page.pretty_title.to_s
end
end
end
-
- public
-
- def self.to_html(text, options = {}, &block)
- TextileFormatter.new(text).to_html(&block)
- end
end
end
--- /dev/null
+# Redmine - project management software
+# Copyright (C) 2006-2008 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+require 'redcloth3'
+require 'coderay'
+
+module Redmine
+ module WikiFormatting
+ module Textile
+ class Formatter < RedCloth3
+
+ # auto_link rule after textile rules so that it doesn't break !image_url! tags
+ RULES = [:textile, :block_markdown_rule, :inline_auto_link, :inline_auto_mailto, :inline_toc, :inline_macros]
+
+ def initialize(*args)
+ super
+ self.hard_breaks=true
+ self.no_span_caps=true
+ end
+
+ def to_html(*rules, &block)
+ @toc = []
+ @macros_runner = block
+ super(*RULES).to_s
+ end
+
+ private
+
+ # Patch for RedCloth. Fixed in RedCloth r128 but _why hasn't released it yet.
+ # <a href="http://code.whytheluckystiff.net/redcloth/changeset/128">http://code.whytheluckystiff.net/redcloth/changeset/128</a>
+ def hard_break( text )
+ text.gsub!( /(.)\n(?!\n|\Z|>| *(>? *[#*=]+(\s|$)|[{|]))/, "\\1<br />\n" ) if hard_breaks
+ end
+
+ # Patch to add code highlighting support to RedCloth
+ def smooth_offtags( text )
+ unless @pre_list.empty?
+ ## replace <pre> content
+ text.gsub!(/<redpre#(\d+)>/) do
+ content = @pre_list[$1.to_i]
+ if content.match(/<code\s+class="(\w+)">\s?(.+)/m)
+ content = "<code class=\"#{$1} CodeRay\">" +
+ CodeRay.scan($2, $1.downcase).html(:escape => false, :line_numbers => :inline)
+ end
+ content
+ end
+ end
+ end
+
+ # Patch to add 'table of content' support to RedCloth
+ def textile_p_withtoc(tag, atts, cite, content)
+ # removes wiki links from the item
+ toc_item = content.gsub(/(\[\[|\]\])/, '')
+ # removes styles
+ # eg. %{color:red}Triggers% => Triggers
+ toc_item.gsub! %r[%\{[^\}]*\}([^%]+)%], '\\1'
+
+ # replaces non word caracters by dashes
+ anchor = toc_item.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-')
+
+ unless anchor.blank?
+ if tag =~ /^h(\d)$/
+ @toc << [$1.to_i, anchor, toc_item]
+ end
+ atts << " id=\"#{anchor}\""
+ content = content + "<a href=\"##{anchor}\" class=\"wiki-anchor\">¶</a>"
+ end
+ textile_p(tag, atts, cite, content)
+ end
+
+ alias :textile_h1 :textile_p_withtoc
+ alias :textile_h2 :textile_p_withtoc
+ alias :textile_h3 :textile_p_withtoc
+
+ def inline_toc(text)
+ text.gsub!(/<p>\{\{([<>]?)toc\}\}<\/p>/i) do
+ div_class = 'toc'
+ div_class << ' right' if $1 == '>'
+ div_class << ' left' if $1 == '<'
+ out = "<ul class=\"#{div_class}\">"
+ @toc.each do |heading|
+ level, anchor, toc_item = heading
+ out << "<li class=\"heading#{level}\"><a href=\"##{anchor}\">#{toc_item}</a></li>\n"
+ end
+ out << '</ul>'
+ out
+ end
+ end
+
+ MACROS_RE = /
+ (!)? # escaping
+ (
+ \{\{ # opening tag
+ ([\w]+) # macro name
+ (\(([^\}]*)\))? # optional arguments
+ \}\} # closing tag
+ )
+ /x unless const_defined?(:MACROS_RE)
+
+ def inline_macros(text)
+ text.gsub!(MACROS_RE) do
+ esc, all, macro = $1, $2, $3.downcase
+ args = ($5 || '').split(',').each(&:strip)
+ if esc.nil?
+ begin
+ @macros_runner.call(macro, args)
+ rescue => e
+ "<div class=\"flash error\">Error executing the <strong>#{macro}</strong> macro (#{e})</div>"
+ end || all
+ else
+ all
+ end
+ end
+ end
+
+ AUTO_LINK_RE = %r{
+ ( # leading text
+ <\w+.*?>| # leading HTML tag, or
+ [^=<>!:'"/]| # leading punctuation, or
+ ^ # beginning of line
+ )
+ (
+ (?:https?://)| # protocol spec, or
+ (?:ftp://)|
+ (?:www\.) # www.*
+ )
+ (
+ (\S+?) # url
+ (\/)? # slash
+ )
+ ([^\w\=\/;\(\)]*?) # post
+ (?=<|\s|$)
+ }x unless const_defined?(:AUTO_LINK_RE)
+
+ # Turns all urls into clickable links (code from Rails).
+ def inline_auto_link(text)
+ text.gsub!(AUTO_LINK_RE) do
+ all, leading, proto, url, post = $&, $1, $2, $3, $6
+ if leading =~ /<a\s/i || leading =~ /![<>=]?/
+ # don't replace URL's that are already linked
+ # and URL's prefixed with ! !> !< != (textile images)
+ all
+ else
+ # 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
+ %(#{leading}<a class="external" href="#{proto=="www."?"http://www.":proto}#{url}">#{proto + url}</a>#{post})
+ end
+ end
+ end
+
+ # Turns all email addresses into clickable links (code from Rails).
+ def inline_auto_mailto(text)
+ text.gsub!(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do
+ mail = $1
+ if text.match(/<a\b[^>]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/)
+ mail
+ else
+ %{<a href="mailto:#{mail}" class="email">#{mail}</a>}
+ end
+ end
+ end
+ end
+ end
+ end
+end
--- /dev/null
+# Redmine - project management software
+# Copyright (C) 2006-2008 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+module Redmine
+ module WikiFormatting
+ module Textile
+ module Helper
+ def wikitoolbar_for(field_id)
+ help_link = l(:setting_text_formatting) + ': ' +
+ link_to(l(:label_help), compute_public_path('wiki_syntax', 'help', 'html'),
+ :onclick => "window.open(\"#{ compute_public_path('wiki_syntax', 'help', 'html') }\", \"\", \"resizable=yes, location=no, width=300, height=640, menubar=no, status=no, scrollbars=yes\"); return false;")
+
+ javascript_include_tag('jstoolbar/jstoolbar') +
+ javascript_include_tag('jstoolbar/textile') +
+ javascript_include_tag("jstoolbar/lang/jstoolbar-#{current_language}") +
+ javascript_tag("var toolbar = new jsToolBar($('#{field_id}')); toolbar.setHelpLink('#{help_link}'); toolbar.draw();")
+ end
+
+ def initial_page_content(page)
+ "h1. #{@page.pretty_title}"
+ end
+
+ def heads_for_wiki_formatter
+ stylesheet_link_tag 'jstoolbar'
+ end
+ end
+ end
+ end
+end
document.removeEventListener('mousemove', this.dragMoveHdlr, false);
document.removeEventListener('mouseup', this.dragStopHdlr, false);
};
-
-// Elements definition ------------------------------------
-
-// strong
-jsToolBar.prototype.elements.strong = {
- type: 'button',
- title: 'Strong',
- fn: {
- wiki: function() { this.singleTag('*') }
- }
-}
-
-// em
-jsToolBar.prototype.elements.em = {
- type: 'button',
- title: 'Italic',
- fn: {
- wiki: function() { this.singleTag("_") }
- }
-}
-
-// ins
-jsToolBar.prototype.elements.ins = {
- type: 'button',
- title: 'Underline',
- fn: {
- wiki: function() { this.singleTag('+') }
- }
-}
-
-// del
-jsToolBar.prototype.elements.del = {
- type: 'button',
- title: 'Deleted',
- fn: {
- wiki: function() { this.singleTag('-') }
- }
-}
-
-// code
-jsToolBar.prototype.elements.code = {
- type: 'button',
- title: 'Code',
- fn: {
- wiki: function() { this.singleTag('@') }
- }
-}
-
-// spacer
-jsToolBar.prototype.elements.space1 = {type: 'space'}
-
-// headings
-jsToolBar.prototype.elements.h1 = {
- type: 'button',
- title: 'Heading 1',
- fn: {
- wiki: function() {
- this.encloseLineSelection('h1. ', '',function(str) {
- str = str.replace(/^h\d+\.\s+/, '')
- return str;
- });
- }
- }
-}
-jsToolBar.prototype.elements.h2 = {
- type: 'button',
- title: 'Heading 2',
- fn: {
- wiki: function() {
- this.encloseLineSelection('h2. ', '',function(str) {
- str = str.replace(/^h\d+\.\s+/, '')
- return str;
- });
- }
- }
-}
-jsToolBar.prototype.elements.h3 = {
- type: 'button',
- title: 'Heading 3',
- fn: {
- wiki: function() {
- this.encloseLineSelection('h3. ', '',function(str) {
- str = str.replace(/^h\d+\.\s+/, '')
- return str;
- });
- }
- }
-}
-
-// spacer
-jsToolBar.prototype.elements.space2 = {type: 'space'}
-
-// ul
-jsToolBar.prototype.elements.ul = {
- type: 'button',
- title: 'Unordered list',
- fn: {
- wiki: function() {
- this.encloseLineSelection('','',function(str) {
- str = str.replace(/\r/g,'');
- return str.replace(/(\n|^)[#-]?\s*/g,"$1* ");
- });
- }
- }
-}
-
-// ol
-jsToolBar.prototype.elements.ol = {
- type: 'button',
- title: 'Ordered list',
- fn: {
- wiki: function() {
- this.encloseLineSelection('','',function(str) {
- str = str.replace(/\r/g,'');
- return str.replace(/(\n|^)[*-]?\s*/g,"$1# ");
- });
- }
- }
-}
-
-// spacer
-jsToolBar.prototype.elements.space3 = {type: 'space'}
-
-// bq
-jsToolBar.prototype.elements.bq = {
- type: 'button',
- title: 'Quote',
- fn: {
- wiki: function() {
- this.encloseLineSelection('','',function(str) {
- str = str.replace(/\r/g,'');
- return str.replace(/(\n|^) *([^\n]*)/g,"$1> $2");
- });
- }
- }
-}
-
-// unbq
-jsToolBar.prototype.elements.unbq = {
- type: 'button',
- title: 'Unquote',
- fn: {
- wiki: function() {
- this.encloseLineSelection('','',function(str) {
- str = str.replace(/\r/g,'');
- return str.replace(/(\n|^) *[>]? *([^\n]*)/g,"$1$2");
- });
- }
- }
-}
-
-// pre
-jsToolBar.prototype.elements.pre = {
- type: 'button',
- title: 'Preformatted text',
- fn: {
- wiki: function() { this.encloseLineSelection('<pre>\n', '\n</pre>') }
- }
-}
-
-// spacer
-jsToolBar.prototype.elements.space4 = {type: 'space'}
-
-// wiki page
-jsToolBar.prototype.elements.link = {
- type: 'button',
- title: 'Wiki link',
- fn: {
- wiki: function() { this.encloseSelection("[[", "]]") }
- }
-}
-// image
-jsToolBar.prototype.elements.img = {
- type: 'button',
- title: 'Image',
- fn: {
- wiki: function() { this.encloseSelection("!", "!") }
- }
-}
--- /dev/null
+/* ***** BEGIN LICENSE BLOCK *****
+ * This file is part of DotClear.
+ * Copyright (c) 2005 Nicolas Martin & Olivier Meunier and contributors. All
+ * rights reserved.
+ *
+ * DotClear is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DotClear is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DotClear; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * ***** END LICENSE BLOCK *****
+*/
+
+/* Modified by JP LANG for textile formatting */
+
+// strong
+jsToolBar.prototype.elements.strong = {
+ type: 'button',
+ title: 'Strong',
+ fn: {
+ wiki: function() { this.singleTag('*') }
+ }
+}
+
+// em
+jsToolBar.prototype.elements.em = {
+ type: 'button',
+ title: 'Italic',
+ fn: {
+ wiki: function() { this.singleTag("_") }
+ }
+}
+
+// ins
+jsToolBar.prototype.elements.ins = {
+ type: 'button',
+ title: 'Underline',
+ fn: {
+ wiki: function() { this.singleTag('+') }
+ }
+}
+
+// del
+jsToolBar.prototype.elements.del = {
+ type: 'button',
+ title: 'Deleted',
+ fn: {
+ wiki: function() { this.singleTag('-') }
+ }
+}
+
+// code
+jsToolBar.prototype.elements.code = {
+ type: 'button',
+ title: 'Code',
+ fn: {
+ wiki: function() { this.singleTag('@') }
+ }
+}
+
+// spacer
+jsToolBar.prototype.elements.space1 = {type: 'space'}
+
+// headings
+jsToolBar.prototype.elements.h1 = {
+ type: 'button',
+ title: 'Heading 1',
+ fn: {
+ wiki: function() {
+ this.encloseLineSelection('h1. ', '',function(str) {
+ str = str.replace(/^h\d+\.\s+/, '')
+ return str;
+ });
+ }
+ }
+}
+jsToolBar.prototype.elements.h2 = {
+ type: 'button',
+ title: 'Heading 2',
+ fn: {
+ wiki: function() {
+ this.encloseLineSelection('h2. ', '',function(str) {
+ str = str.replace(/^h\d+\.\s+/, '')
+ return str;
+ });
+ }
+ }
+}
+jsToolBar.prototype.elements.h3 = {
+ type: 'button',
+ title: 'Heading 3',
+ fn: {
+ wiki: function() {
+ this.encloseLineSelection('h3. ', '',function(str) {
+ str = str.replace(/^h\d+\.\s+/, '')
+ return str;
+ });
+ }
+ }
+}
+
+// spacer
+jsToolBar.prototype.elements.space2 = {type: 'space'}
+
+// ul
+jsToolBar.prototype.elements.ul = {
+ type: 'button',
+ title: 'Unordered list',
+ fn: {
+ wiki: function() {
+ this.encloseLineSelection('','',function(str) {
+ str = str.replace(/\r/g,'');
+ return str.replace(/(\n|^)[#-]?\s*/g,"$1* ");
+ });
+ }
+ }
+}
+
+// ol
+jsToolBar.prototype.elements.ol = {
+ type: 'button',
+ title: 'Ordered list',
+ fn: {
+ wiki: function() {
+ this.encloseLineSelection('','',function(str) {
+ str = str.replace(/\r/g,'');
+ return str.replace(/(\n|^)[*-]?\s*/g,"$1# ");
+ });
+ }
+ }
+}
+
+// spacer
+jsToolBar.prototype.elements.space3 = {type: 'space'}
+
+// bq
+jsToolBar.prototype.elements.bq = {
+ type: 'button',
+ title: 'Quote',
+ fn: {
+ wiki: function() {
+ this.encloseLineSelection('','',function(str) {
+ str = str.replace(/\r/g,'');
+ return str.replace(/(\n|^) *([^\n]*)/g,"$1> $2");
+ });
+ }
+ }
+}
+
+// unbq
+jsToolBar.prototype.elements.unbq = {
+ type: 'button',
+ title: 'Unquote',
+ fn: {
+ wiki: function() {
+ this.encloseLineSelection('','',function(str) {
+ str = str.replace(/\r/g,'');
+ return str.replace(/(\n|^) *[>]? *([^\n]*)/g,"$1$2");
+ });
+ }
+ }
+}
+
+// pre
+jsToolBar.prototype.elements.pre = {
+ type: 'button',
+ title: 'Preformatted text',
+ fn: {
+ wiki: function() { this.encloseLineSelection('<pre>\n', '\n</pre>') }
+ }
+}
+
+// spacer
+jsToolBar.prototype.elements.space4 = {type: 'space'}
+
+// wiki page
+jsToolBar.prototype.elements.link = {
+ type: 'button',
+ title: 'Wiki link',
+ fn: {
+ wiki: function() { this.encloseSelection("[[", "]]") }
+ }
+}
+// image
+jsToolBar.prototype.elements.img = {
+ type: 'button',
+ title: 'Image',
+ fn: {
+ wiki: function() { this.encloseSelection("!", "!") }
+ }
+}
assert textilizable(text).match(/Unknow project/)
end
+ def test_default_formatter
+ Setting.text_formatting = 'unknown'
+ text = 'a *link*: http://www.example.net/'
+ assert_equal '<p>a *link*: <a href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text)
+ Setting.text_formatting = 'textile'
+ end
+
def test_date_format_default
today = Date.today
Setting.date_format = ''