0byt3m1n1
Path:
/
data
/
applications
/
aps
/
phpwiki
/
1.4.0-0
/
standard
/
htdocs
/
themes
/
default
/
Wikiwyg
/
Wikiwyg
/
[
Home
]
File: Wikitext.js
/*============================================================================== This Wikiwyg mode supports a textarea editor with toolbar buttons. COPYRIGHT: Copyright (c) 2005 Socialtext Corporation 655 High Street Palo Alto, CA 94301 U.S.A. All rights reserved. Wikiwyg is free software. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. http://www.gnu.org/copyleft/lesser.txt =============================================================================*/ proto = new Subclass('Wikiwyg.Wikitext', 'Wikiwyg.Mode'); klass = Wikiwyg.Wikitext; proto.classtype = 'wikitext'; proto.modeDescription = 'Wikitext'; proto.config = { supportCamelCaseLinks: false, javascriptLocation: null, clearRegex: null, editHeightMinimum: 10, editHeightAdjustment: 1.3, markupRules: { link: ['bound_phrase', '[', ']'], bold: ['bound_phrase', '*', '*'], code: ['bound_phrase', '`', '`'], italic: ['bound_phrase', '/', '/'], underline: ['bound_phrase', '_', '_'], strike: ['bound_phrase', '-', '-'], p: ['start_lines', ''], pre: ['start_lines', ' '], h1: ['start_line', '= '], h2: ['start_line', '== '], h3: ['start_line', '=== '], h4: ['start_line', '==== '], h5: ['start_line', '===== '], h6: ['start_line', '====== '], ordered: ['start_lines', '#'], unordered: ['start_lines', '*'], indent: ['start_lines', '>'], hr: ['line_alone', '----'], table: ['line_alone', '| A | B | C |\n| | | |\n| | | |'] } } proto.initializeObject = function() { // See IE this.initialize_object(); } proto.initialize_object = function() { this.div = document.createElement('div'); this.textarea = document.createElement('textarea'); this.textarea.setAttribute('id', 'wikiwyg_wikitext_textarea'); this.div.appendChild(this.textarea); this.area = this.textarea; this.clear_inner_text(); } proto.clear_inner_text = function() { var self = this; this.area.onclick = function() { var inner_text = self.area.value; var clear = self.config.clearRegex; if (clear && inner_text.match(clear)) self.area.value = ''; } } proto.enableThis = function() { this.superfunc('enableThis').call(this); this.textarea.style.width = '100%'; this.setHeightOfEditor(); this.enable_keybindings(); } proto.setHeightOfEditor = function() { var config = this.config; var adjust = config.editHeightAdjustment; var area = this.textarea; var text = this.textarea.value; var rows = text.split(/\n/).length; var height = parseInt(rows * adjust); if (height < config.editHeightMinimum) height = config.editHeightMinimum; area.setAttribute('rows', height); } proto.toWikitext = function() { return this.textarea.value; } proto.toHtml = function(func) { var wikitext = this.textarea.value; this.convertWikitextToHtml(wikitext, func); } proto.fromHtml = function(html) { this.textarea.value = 'Loading...'; var textarea = this.textarea; this.convertHtmlToWikitext( html, function(value) { textarea.value = value } ); } proto.fromWikitext = function(html) { this.textarea.value = html; } proto.convertWikitextToHtml = function(wikitext, func) { alert('Wikitext changes cannot be converted to HTML\nWikiwyg.Wikitext.convertWikitextToHtml is not implemented here'); func(this.copyhtml); } proto.convertHtmlToWikitext = function(html, func) { func(this.convert_html_to_wikitext(html)); } proto.get_keybinding_area = function() { return this.textarea; } /*============================================================================== Code to markup wikitext =============================================================================*/ Wikiwyg.Wikitext.phrase_end_re = /[\s\.\:\;\,\!\?\(\)]/; proto.find_left = function(t, selection_start, matcher) { var substring = t.substr(selection_start - 1, 1); var nextstring = t.substr(selection_start - 2, 1); if (selection_start == 0) return selection_start; if (substring.match(matcher)) { // special case for word.word if ((substring != '.') || (nextstring.match(/\s/))) return selection_start; } return this.find_left(t, selection_start - 1, matcher); } proto.find_right = function(t, selection_end, matcher) { var substring = t.substr(selection_end, 1); var nextstring = t.substr(selection_end + 1, 1); if (selection_end >= t.length) return selection_end; if (substring.match(matcher)) { // special case for word.word if ((substring != '.') || (nextstring.match(/\s/))) return selection_end; } return this.find_right(t, selection_end + 1, matcher); } proto.get_lines = function() { t = this.area; var selection_start = t.selectionStart; var selection_end = t.selectionEnd; if (selection_start == null || selection_end == null) return false var our_text = t.value.replace(/\r/g, ''); selection = our_text.substr(selection_start, selection_end - selection_start); selection_start = this.find_right(our_text, selection_start, /[^\r\n]/); selection_end = this.find_left(our_text, selection_end, /[^\r\n]/); this.selection_start = this.find_left(our_text, selection_start, /[\r\n]/); this.selection_end = this.find_right(our_text, selection_end, /[\r\n]/); t.setSelectionRange(selection_start, selection_end); t.focus(); this.start = our_text.substr(0,this.selection_start); this.sel = our_text.substr(this.selection_start, this.selection_end - this.selection_start); this.finish = our_text.substr(this.selection_end, our_text.length); return true; } proto.alarm_on = function() { var area = this.area; var background = area.style.background; area.style.background = '#f88'; function alarm_off() { area.style.background = background; } window.setTimeout(alarm_off, 250); area.focus() } proto.get_words = function() { function is_insane(selection) { return selection.match(/\r?\n(\r?\n|\*+ |\#+ |\=+ )/); } t = this.area; var selection_start = t.selectionStart; var selection_end = t.selectionEnd; if (selection_start == null || selection_end == null) return false; var our_text = t.value.replace(/\r/g, ''); selection = our_text.substr(selection_start, selection_end - selection_start); selection_start = this.find_right(our_text, selection_start, /(\S|\r?\n)/); if (selection_start > selection_end) selection_start = selection_end; selection_end = this.find_left(our_text, selection_end, /(\S|\r?\n)/); if (selection_end < selection_start) selection_end = selection_start; if (is_insane(selection)) { this.alarm_on(); return false; } this.selection_start = this.find_left(our_text, selection_start, Wikiwyg.Wikitext.phrase_end_re); this.selection_end = this.find_right(our_text, selection_end, Wikiwyg.Wikitext.phrase_end_re); t.setSelectionRange(this.selection_start, this.selection_end); t.focus(); this.start = our_text.substr(0,this.selection_start); this.sel = our_text.substr(this.selection_start, this.selection_end - this.selection_start); this.finish = our_text.substr(this.selection_end, our_text.length); return true; } proto.markup_is_on = function(start, finish) { return (this.sel.match(start) && this.sel.match(finish)); } proto.clean_selection = function(start, finish) { this.sel = this.sel.replace(start, ''); this.sel = this.sel.replace(finish, ''); } proto.toggle_same_format = function(start, finish) { start = this.clean_regexp(start); finish = this.clean_regexp(finish); var start_re = new RegExp('^' + start); var finish_re = new RegExp(finish + '$'); if (this.markup_is_on(start_re, finish_re)) { this.clean_selection(start_re, finish_re); return true; } return false; } proto.clean_regexp = function(string) { string = string.replace(/([\^\$\*\+\.\?\[\]\{\}\|])/g, '\\$1'); return string; } proto.set_text_and_selection = function(text, start, end) { this.area.value = text; this.area.setSelectionRange(start, end); } proto.add_markup_words = function(markup_start, markup_finish, example) { if (this.toggle_same_format(markup_start, markup_finish)) { this.selection_end = this.selection_end - (markup_start.length + markup_finish.length); markup_start = ''; markup_finish = ''; } if (this.sel.length == 0) { if (example) this.sel = example; var text = this.start + markup_start + this.sel + markup_finish + this.finish; var start = this.selection_start + markup_start.length; var end = this.selection_end + markup_start.length + this.sel.length; this.set_text_and_selection(text, start, end); } else { var text = this.start + markup_start + this.sel + markup_finish + this.finish; var start = this.selection_start; var end = this.selection_end + markup_start.length + markup_finish.length; this.set_text_and_selection(text, start, end); } this.area.focus(); } // XXX - A lot of this is hardcoded. proto.add_markup_lines = function(markup_start) { var already_set_re = new RegExp( '^' + this.clean_regexp(markup_start), 'gm'); var other_markup_re = /^(\^+|\=+|\*+|#+|>+| )/gm; var match; // if paragraph, reduce everything. if (! markup_start.length) { this.sel = this.sel.replace(other_markup_re, ''); this.sel = this.sel.replace(/^\ +/gm, ''); } // if pre and not all indented, indent else if ((markup_start == ' ') && this.sel.match(/^\S/m)) this.sel = this.sel.replace(/^/gm, markup_start); // if not requesting heading and already this style, kill this style else if ( (! markup_start.match(/[\=\^]/)) && this.sel.match(already_set_re) ) { this.sel = this.sel.replace(already_set_re, ''); if (markup_start != ' ') this.sel = this.sel.replace(/^ */gm, ''); } // if some other style, switch to new style else if (match = this.sel.match(other_markup_re)) // if pre, just indent if (markup_start == ' ') this.sel = this.sel.replace(/^/gm, markup_start); // if heading, just change it else if (markup_start.match(/[\=\^]/)) this.sel = this.sel.replace(other_markup_re, markup_start); // else try to change based on level else this.sel = this.sel.replace( other_markup_re, function(match) { return markup_start.times(match.length); } ); // if something selected, use this style else if (this.sel.length > 0) this.sel = this.sel.replace(/^(.*\S+)/gm, markup_start + ' $1'); // just add the markup else this.sel = markup_start + ' '; var text = this.start + this.sel + this.finish; var start = this.selection_start; var end = this.selection_start + this.sel.length; this.set_text_and_selection(text, start, end); this.area.focus(); } // XXX - A lot of this is hardcoded. proto.bound_markup_lines = function(markup_array) { var markup_start = markup_array[1]; var markup_finish = markup_array[2]; var already_start = new RegExp('^' + this.clean_regexp(markup_start), 'gm'); var already_finish = new RegExp(this.clean_regexp(markup_finish) + '$', 'gm'); var other_start = /^(\^+|\=+|\*+|#+|>+) */gm; var other_finish = /( +(\^+|\=+))?$/gm; var match; if (this.sel.match(already_start)) { this.sel = this.sel.replace(already_start, ''); this.sel = this.sel.replace(already_finish, ''); } else if (match = this.sel.match(other_start)) { this.sel = this.sel.replace(other_start, markup_start); this.sel = this.sel.replace(other_finish, markup_finish); } // if something selected, use this style else if (this.sel.length > 0) { this.sel = this.sel.replace( /^(.*\S+)/gm, markup_start + '$1' + markup_finish ); } // just add the markup else this.sel = markup_start + markup_finish; var text = this.start + this.sel + this.finish; var start = this.selection_start; var end = this.selection_start + this.sel.length; this.set_text_and_selection(text, start, end); this.area.focus(); } proto.markup_bound_line = function(markup_array) { var scroll_top = this.area.scrollTop; if (this.get_lines()) this.bound_markup_lines(markup_array); this.area.scrollTop = scroll_top; } proto.markup_start_line = function(markup_array) { var markup_start = markup_array[1]; markup_start = markup_start.replace(/ +/, ''); var scroll_top = this.area.scrollTop; if (this.get_lines()) this.add_markup_lines(markup_start); this.area.scrollTop = scroll_top; } proto.markup_start_lines = function(markup_array) { var markup_start = markup_array[1]; var scroll_top = this.area.scrollTop; if (this.get_lines()) this.add_markup_lines(markup_start); this.area.scrollTop = scroll_top; } proto.markup_bound_phrase = function(markup_array) { var markup_start = markup_array[1]; var markup_finish = markup_array[2]; var scroll_top = this.area.scrollTop; if (markup_finish == 'undefined') markup_finish = markup_start; if (this.get_words()) this.add_markup_words(markup_start, markup_finish, null); this.area.scrollTop = scroll_top; } klass.make_do = function(style) { return function() { var markup = this.config.markupRules[style]; var handler = markup[0]; if (! this['markup_' + handler]) die('No handler for markup: "' + handler + '"'); this['markup_' + handler](markup); } } proto.do_link = klass.make_do('link'); proto.do_bold = klass.make_do('bold'); proto.do_code = klass.make_do('code'); proto.do_italic = klass.make_do('italic'); proto.do_underline = klass.make_do('underline'); proto.do_strike = klass.make_do('strike'); proto.do_p = klass.make_do('p'); proto.do_pre = klass.make_do('pre'); proto.do_h1 = klass.make_do('h1'); proto.do_h2 = klass.make_do('h2'); proto.do_h3 = klass.make_do('h3'); proto.do_h4 = klass.make_do('h4'); proto.do_h5 = klass.make_do('h5'); proto.do_h6 = klass.make_do('h6'); proto.do_ordered = klass.make_do('ordered'); proto.do_unordered = klass.make_do('unordered'); proto.do_hr = klass.make_do('hr'); proto.do_table = klass.make_do('table'); proto.do_dent = function(method) { var scroll_top = this.area.scrollTop; if (! this.get_lines()) { this.area.scrollTop = scroll_top; return; } if (method(this)) { var text = this.start + this.sel + this.finish; var start = this.selection_start; var end = this.selection_start + this.sel.length; this.set_text_and_selection(text, start, end); } this.area.focus(); } proto.do_indent = function() { this.do_dent( function(that) { if (that.sel == '') return false; that.sel = that.sel.replace(/^(([\*\-\#])+(?=\s))/gm, '$2$1'); that.sel = that.sel.replace(/^([\>\=])/gm, '$1$1'); that.sel = that.sel.replace(/^([^\>\*\-\#\=\r\n])/gm, '> $1'); that.sel = that.sel.replace(/^\={7,}/gm, '======'); return true; } ) } proto.do_outdent = function() { this.do_dent( function(that) { if (that.sel == '') return false; that.sel = that.sel.replace(/^([\>\*\-\#\=] ?)/gm, ''); return true; } ) } proto.markup_line_alone = function(markup_array) { var t = this.area; var scroll_top = t.scrollTop; var selection_start = t.selectionStart; var text = t.value; this.selection_start = this.find_right(text, selection_start, /\r?\n/); this.selection_end = this.selection_start; t.setSelectionRange(this.selection_start, this.selection_start); t.focus(); var markup = markup_array[1]; this.start = t.value.substr(0, this.selection_start); this.finish = t.value.substr(this.selection_end, t.value.length); var text = this.start + '\n' + markup + this.finish; var start = this.selection_start + markup.length + 1; var end = this.selection_end + markup.length + 1; this.set_text_and_selection(text, start, end); t.scrollTop = scroll_top; } /*============================================================================== Code to convert from html to wikitext. =============================================================================*/ proto.convert_html_to_wikitext = function(html) { this.copyhtml = html; var dom = document.createElement('div'); html = html.replace(/<!-=-/g, '<!--'). replace(/-=->/g, '-->'); dom.innerHTML = html; this.output = []; this.list_type = []; this.indent_level = 0; this.walk(dom); // add final whitespace this.assert_new_line(); return this.join_output(this.output); } proto.appendOutput = function(string) { this.output.push(string); } proto.join_output = function(output) { var list = this.remove_stops(output); list = this.cleanup_output(list); return list.join(''); } // This is a noop, but can be subclassed. proto.cleanup_output = function(list) { return list; } proto.remove_stops = function(list) { var clean = []; for (var i = 0 ; i < list.length ; i++) { if (typeof(list[i]) != 'string') continue; clean.push(list[i]); } return clean; } proto.walk = function(element) { if (!element) return; for (var part = element.firstChild; part; part = part.nextSibling) { if (part.nodeType == 1) { this.dispatch_formatter(part); } else if (part.nodeType == 3) { if (part.nodeValue.match(/\S/)) { var string = part.nodeValue; if (! string.match(/^[\.\,\?\!\)]/)) { this.assert_space_or_newline(); string = this.trim(string); } this._tag = "text"; this.appendOutput(this.collapse(string)); this._tag = "false"; } } } } proto.dispatch_formatter = function(element) { var dispatch = 'format_' + element.nodeName.toLowerCase(); if (! this[dispatch]) dispatch = 'handle_undefined'; this[dispatch](element); } proto.skip = function() { } proto.pass = function(element) { this.walk(element); } proto.handle_undefined = function(element) { this.appendOutput('<' + element.nodeName + '>'); this.walk(element); this.appendOutput('</' + element.nodeName + '>'); } proto.handle_undefined = proto.skip; proto.format_abbr = proto.pass; proto.format_acronym = proto.pass; proto.format_address = proto.pass; proto.format_applet = proto.skip; proto.format_area = proto.skip; proto.format_basefont = proto.skip; proto.format_base = proto.skip; proto.format_bgsound = proto.skip; proto.format_big = proto.pass; proto.format_blink = proto.pass; proto.format_body = proto.pass; proto.format_br = proto.skip; proto.format_button = proto.skip; proto.format_caption = proto.pass; proto.format_center = proto.pass; proto.format_cite = proto.pass; proto.format_col = proto.pass; proto.format_colgroup = proto.pass; proto.format_dd = proto.pass; proto.format_dfn = proto.pass; proto.format_dl = proto.pass; proto.format_dt = proto.pass; proto.format_embed = proto.skip; proto.format_field = proto.skip; proto.format_fieldset = proto.skip; proto.format_font = proto.pass; proto.format_form = proto.skip; proto.format_frame = proto.skip; proto.format_frameset = proto.skip; proto.format_head = proto.skip; proto.format_html = proto.pass; proto.format_iframe = proto.pass; proto.format_input = proto.skip; proto.format_ins = proto.pass; proto.format_isindex = proto.skip; proto.format_label = proto.skip; proto.format_legend = proto.skip; proto.format_link = proto.skip; proto.format_map = proto.skip; proto.format_marquee = proto.skip; proto.format_meta = proto.skip; proto.format_multicol = proto.pass; proto.format_nobr = proto.skip; proto.format_noembed = proto.skip; proto.format_noframes = proto.skip; proto.format_nolayer = proto.skip; proto.format_noscript = proto.skip; proto.format_nowrap = proto.skip; proto.format_object = proto.skip; proto.format_optgroup = proto.skip; proto.format_option = proto.skip; proto.format_param = proto.skip; proto.format_select = proto.skip; proto.format_small = proto.pass; proto.format_spacer = proto.skip; proto.format_style = proto.skip; proto.format_sub = proto.pass; proto.format_submit = proto.skip; proto.format_sup = proto.pass; proto.format_tbody = proto.pass; proto.format_textarea = proto.skip; proto.format_tfoot = proto.pass; proto.format_thead = proto.pass; proto.format_wiki = proto.pass; proto.format_img = function(element) { var uri = element.getAttribute('src'); if (uri) { this.assert_space_or_newline(); this.appendOutput(uri); } } // XXX This little dance relies on knowning lots of little details about where // indentation fangs are added and deleted by the various insert/assert calls. proto.format_blockquote = function(element) { if (! this.indent_level) { this.assert_new_line(); this.indent_level++; this.insert_new_line(); } else { this.indent_level++; this.assert_new_line(); } this.walk(element); this.indent_level--; if (! this.indent_level) this.assert_blank_line(); else this.assert_new_line(); } proto.format_div = function(element) { if (this.is_opaque(element)) { this.handle_opaque_block(element); return; } this.walk(element); } proto.format_span = function(element) { if (this.is_opaque(element)) { this.handle_opaque_phrase(element); return; } var style = element.getAttribute('style'); if (!style) { this.pass(element); return; } this.assert_space_or_newline(); if (style.match(/\bbold\b/)) this.appendOutput(this.config.markupRules.bold[1]); if (style.match(/\bitalic\b/)) this.appendOutput(this.config.markupRules.italic[1]); if (style.match(/\bunderline\b/)) this.appendOutput(this.config.markupRules.underline[1]); if (style.match(/\bline-through\b/)) this.appendOutput(this.config.markupRules.strike[1]); this.no_following_whitespace(); this.walk(element); if (style.match(/\bline-through\b/)) this.appendOutput(this.config.markupRules.strike[2]); if (style.match(/\bunderline\b/)) this.appendOutput(this.config.markupRules.underline[2]); if (style.match(/\bitalic\b/)) this.appendOutput(this.config.markupRules.italic[2]); if (style.match(/\bbold\b/)) this.appendOutput(this.config.markupRules.bold[2]); } klass.make_format = function(style) { return function(element) { var markup = this.config.markupRules[style]; var handler = markup[0]; this['handle_' + handler](element, markup); } } proto.format_b = klass.make_format('bold'); proto.format_strong = proto.format_b; proto.format_code = klass.make_format('code'); proto.format_kbd = proto.format_code; proto.format_samp = proto.format_code; proto.format_tt = proto.format_code; proto.format_var = proto.format_code; proto.format_i = klass.make_format('italic'); proto.format_em = proto.format_i; proto.format_u = klass.make_format('underline'); proto.format_strike = klass.make_format('strike'); proto.format_del = proto.format_strike; proto.format_s = proto.format_strike; proto.format_hr = klass.make_format('hr'); proto.format_h1 = klass.make_format('h1'); proto.format_h2 = klass.make_format('h2'); proto.format_h3 = klass.make_format('h3'); proto.format_h4 = klass.make_format('h4'); proto.format_h5 = klass.make_format('h5'); proto.format_h6 = klass.make_format('h6'); proto.format_pre = klass.make_format('pre'); proto.format_p = function(element) { this.assert_blank_line(); this.walk(element); this.assert_blank_line(); } proto.format_a = function(element) { var label = Wikiwyg.htmlUnescape(element.innerHTML); label = label.replace(/<[^>]*?>/g, ' '); label = label.replace(/\s+/g, ' '); label = label.replace(/^\s+/, ''); label = label.replace(/\s+$/, ''); this.make_wikitext_link(label, element.getAttribute('href'), element); } proto.format_table = function(element) { this.assert_blank_line(); this.walk(element); this.assert_blank_line(); } proto.format_tr = function(element) { this.walk(element); this.appendOutput('|'); this.insert_new_line(); } proto.format_td = function(element) { this.appendOutput('| '); this.walk(element); this.appendOutput(' '); } proto.format_th = proto.format_td; proto.format_ol = function(element) { if (!this.list_type.length) this.assert_blank_line(); else this.assert_new_line(); this.list_type.push('ordered'); this.walk(element); this.list_type.pop(); if (!this.list_type.length) this.assert_blank_line(); } // XXX - Maybe a refactoring for the duplication above proto.format_ul = function(element) { if (!this.list_type.length) this.assert_blank_line(); else this.assert_new_line(); this.list_type.push('unordered'); this.walk(element); this.list_type.pop(); if (!this.list_type.length) this.assert_blank_line(); } proto.format_li = function(element) { var level = this.list_type.length; if (!level) die("List error"); var type = this.list_type[level - 1]; var markup = this.config.markupRules[type]; this.appendOutput(markup[1].times(level) + ' '); this.walk(element); this.chomp(); this.insert_new_line(); } proto.chomp = function() { var string; while (this.output.length) { string = this.output.pop(); if (typeof(string) != 'string') { this.appendOutput(string); return; } if (! string.match(/^\n>+ $/) && string.match(/\S/)) break; } if (string) { string = string.replace(/[\r\n\s]+$/, ''); this.appendOutput(string); } } proto.collapse = function(string) { return string.replace(/[ \r\n]+/g, ' '); } proto.trim = function(string) { return string.replace(/^\s+/, ''); } proto.insert_new_line = function() { var fang = ''; if (this.indent_level > 0) fang = '>'.times(this.indent_level) + ' '; // XXX - ('\n' + fang) MUST be in the same element in this.output so that // it can be properly matched by chomp above. if (this.output.length) this.appendOutput('\n' + fang); else if (fang.length) this.appendOutput(fang); } proto.assert_new_line = function() { this.chomp(); this.insert_new_line(); } proto.assert_blank_line = function() { this.chomp(); this.insert_new_line(); this.insert_new_line(); } proto.assert_space_or_newline = function() { var string; if (! this.output.length) return; string = this.output[this.output.length - 1]; if (! string.whitespace && ! string.match(/\s+$/)) this.appendOutput(' '); } proto.no_following_whitespace = function() { this.appendOutput({whitespace: 'stop'}); } proto.handle_bound_phrase = function(element, markup) { this.assert_space_or_newline(); this.appendOutput(markup[1]); this.no_following_whitespace(); this.walk(element); // assume that walk leaves no trailing whitespace. this.appendOutput(markup[2]); } // XXX - A very promising refactoring is that we don't need the trailing // assert_blank_line in block formatters. proto.handle_bound_line = function(element,markup) { this.assert_blank_line(); this.appendOutput(markup[1]); this.walk(element); this.appendOutput(markup[2]); this.assert_blank_line(); } proto.handle_start_line = function (element, markup) { this.assert_blank_line(); this.appendOutput(markup[1]); this.walk(element); this.assert_blank_line(); } proto.handle_start_lines = function (element, markup) { var text = element.firstChild.nodeValue; if (!text) return; this.assert_blank_line(); text = text.replace(/^/mg, markup[1]); this.appendOutput(text); this.assert_blank_line(); } proto.handle_line_alone = function (element, markup) { this.assert_blank_line(); this.appendOutput(markup[1]); this.assert_blank_line(); } proto.get_first_comment = function(element) { var comment = element.firstChild; if (comment && (comment.nodeType == 8)) return comment; else return null; } proto.is_opaque = function(element) { var comment = this.get_first_comment(element); if (!comment) return false; var text = comment.data; if (text.match(/^\s*wiki:/)) return true; return false; } proto.handle_opaque_phrase = function(element) { var comment = this.get_first_comment(element); if (comment) { var text = comment.data; text = text.replace(/^ wiki:\s+/, ''); text = text.replace(/\s$/, ''); this.assert_space_or_newline(); this.appendOutput(text); this.assert_space_or_newline(); } } proto.handle_opaque_block = function(element) { var comment = this.get_first_comment(element); if (!comment) return; var text = comment.data; text = text.replace(/^\s*wiki:\s+/, ''); this.appendOutput(text); } proto.make_wikitext_link = function(label, href, element) { var before = this.config.markupRules.link[1]; var after = this.config.markupRules.link[2]; this.assert_space_or_newline(); if (! href) { this.appendOutput(label); } else if (href == label) { this.appendOutput(href); } else if (this.href_is_wiki_link(href)) { if (this.camel_case_link(label)) this.appendOutput(label); else this.appendOutput(before + label + after); } else { this.appendOutput(before + href + ' ' + label + after); } } proto.camel_case_link = function(label) { if (! this.config.supportCamelCaseLinks) return false; return label.match(/[a-z][A-Z]/); } proto.href_is_wiki_link = function(href) { if (! this.looks_like_a_url(href)) return true; if (! href.match(/\?/)) return false; var no_arg_input = href.split('?')[0]; var no_arg_current = location.href.split('?')[0]; return no_arg_input == no_arg_current; } proto.looks_like_a_url = function(string) { return string.match(/^(http|https|ftp|irc|mailto):/); } /*============================================================================== Support for Internet Explorer in Wikiwyg.Wikitext =============================================================================*/ if (Wikiwyg.is_ie) { proto.setHeightOf = function() { // XXX hardcode this until we can keep window from jumping after button // events. this.textarea.style.height = '200px'; } proto.initializeObject = function() { this.initialize_object(); this.area.addBehavior(this.config.javascriptLocation + "Selection.htc"); } } // end of global if