# HG changeset patch # User Dan Fuhry # Date 1307006908 14400 # Node ID 2a31905a567dc9d179c2ed11fd6687b7045a03d9 # Parent 2164d18cb10c9541a4c5790ca8cc02022b868275 Removed explicit TinyMCE support, replaced with support for arbitrary page_formats. The TinyMCE files will be removed in an upcoming commit. diff -r 2164d18cb10c -r 2a31905a567d ajax.php --- a/ajax.php Thu Jun 02 05:24:38 2011 -0400 +++ b/ajax.php Thu Jun 02 05:28:28 2011 -0400 @@ -77,18 +77,10 @@ ); $return['page_format'] = $page->ns->cdata['page_format']; - if ( $return['page_format'] == 'xhtml' ) + $code = $plugins->setHook('get_page_source'); + foreach ( $code as $cmd ) { - // gently process headings to make tinymce format them correctly - if ( preg_match_all('/^ *?(={1,6}) *(.+?) *\\1 *$/m', $return['src'], $matches) ) - { - foreach ( $matches[0] as $i => $match ) - { - $hi = strlen($matches[1][$i]); - $heading = "{$matches[2][$i]}"; - $return['src'] = str_replace_once($match, $heading, $return['src']); - } - } + eval($cmd); } if ( $have_draft ) @@ -244,32 +236,32 @@ else { $src = RenderMan::preprocess_text($request['src'], false, false); - $draft_format = $request['format']; - if ( !in_array($draft_format, array('xhtml', 'wikitext')) ) + $draft_format = $db->escape($request['format']); + + // Save the draft + if ( !preg_match('/^[a-z0-9_]+$/', $draft_format) ) { $return = array( - 'mode' => 'error', - 'error' => 'invalid_format' - ); + 'mode' => 'error', + 'error' => 'Page format must match /^[a-z0-9_]+$/' + ); } else { - // Save the draft $q = $db->sql_query('INSERT INTO ' . table_prefix . 'logs ( log_type, action, page_id, namespace, author, author_uid, edit_summary, page_text, is_draft, time_id, page_format ) - VALUES ( - \'page\', - \'edit\', - \'' . $db->escape($paths->page_id) . '\', - \'' . $db->escape($paths->namespace) . '\', - \'' . $db->escape($session->username) . '\', - ' . $session->user_id . ', - \'' . $db->escape($request['summary']) . '\', - \'' . $db->escape($src) . '\', - 1, - ' . time() . ', - \'' . $draft_format . '\' - );'); - + VALUES ( + \'page\', + \'edit\', + \'' . $db->escape($paths->page_id) . '\', + \'' . $db->escape($paths->namespace) . '\', + \'' . $db->escape($session->username) . '\', + ' . $session->user_id . ', + \'' . $db->escape($request['summary']) . '\', + \'' . $db->escape($src) . '\', + 1, + ' . time() . ', + \'' . $draft_format . '\' + );'); // Done! $return = array( 'mode' => 'success', @@ -302,7 +294,7 @@ } // Verify captcha, if needed - if ( false && !$session->user_logged_in && getConfig('guest_edit_require_captcha') == '1' ) + if ( !$session->user_logged_in && getConfig('guest_edit_require_captcha') == '1' ) { if ( !isset($request['captcha_id']) || !isset($request['captcha_code']) ) { diff -r 2164d18cb10c -r 2a31905a567d includes/clientside/static/editor.js --- a/includes/clientside/static/editor.js Thu Jun 02 05:24:38 2011 -0400 +++ b/includes/clientside/static/editor.js Thu Jun 02 05:28:28 2011 -0400 @@ -8,6 +8,7 @@ var editor_wikitext_transform_enable = true; var editor_orig_text = ''; var editor_last_draft = ''; +var page_format = 'wikitext'; window.ajaxEditor = function(revid) { @@ -146,15 +147,15 @@ span_mce.appendChild(a); toggler.appendChild(span_mce); - if ( response.page_format == 'xhtml' ) + if ( response.page_format == 'wikitext' ) { - // Current selection is TinyMCE - make span_wiki have the link and span_mce be plaintext - span_mce.style.display = 'none'; + // Current selection is a custom editor plugin - make span_wiki have the link and span_mce be plaintext + span_wiki.style.display = 'none'; } else { // Current selection is wikitext - set span_wiki to plaintext and span_mce to link - span_wiki.style.display = 'none'; + span_mce.style.display = 'none'; } } @@ -493,9 +494,32 @@ editor_orig_text = content; // If the editor preference is tinymce, switch the editor to TinyMCE now - if ( response.page_format == 'xhtml' && allow_wysiwyg ) + if ( response.page_format != 'wikitext' && allow_wysiwyg ) { - $dynano('ajaxEditArea').switchToMCE(false); + if ( typeof(editor_formats[response.page_format]) == 'object' ) + { + // instruct the editor plugin to go ahead and build its UI + editor_formats[response.page_format].ui_construct(); + window.page_format = response.page_format; + } + else + { + // Page was formatted with a plugin that no longer exists + miniPromptMessage({ + title: $lang.get('editor_msg_convert_missing_plugin_title'), + message: $lang.get('editor_msg_convert_missing_plugin_body', { plugin: response.page_format }), + buttons: [ + { + text: $lang.get('etc_ok'), + onclick: function() + { + miniPromptDestroy(this); + return false; + } + } + ] + }); + } } if ( allow_wysiwyg ) @@ -549,7 +573,7 @@ else editor_save_lock = true; - var ta_content = ( text_override ) ? text_override : $dynano('ajaxEditArea').getContent(); + var ta_content = ( text_override ) ? text_override : ajaxEditorGetContent(); if ( !is_draft && ( ta_content == '' || ta_content == '

' || ta_content == '

 

' ) ) { @@ -585,7 +609,7 @@ minor_edit: is_minor, time: timestamp, draft: ( is_draft == true ), - format: ( $dynano('ajaxEditArea').isMCE() ) ? 'xhtml' : 'wikitext', + format: window.page_format, used_draft: used_draft }; @@ -696,7 +720,13 @@ editor_open = false; editor_save_lock = false; enableUnload(); - $dynano('ajaxEditArea').destroyMCE(false); + if ( window.page_format != 'wikitext' ) + { + if ( typeof(editor_formats[window.page_format].ui_destroy) == 'function' ) + { + editor_formats[window.page_format].ui_destroy(); + } + } changeOpac(0, 'ajaxEditContainer'); ajaxGet(stdAjaxPrefix + '&_mode=getpage&noheaders', function(ajax) { @@ -759,7 +789,7 @@ window.ajaxEditorGenPreview = function() { ajaxSetEditorLoading(); - var ta_content = $dynano('ajaxEditArea').getContent(); + var ta_content = ajaxEditorGetContent(); ta_content = ajaxEscape(ta_content); if ( $dynano('enano_editor_preview').object.innerHTML != '' ) { @@ -853,7 +883,7 @@ window.ajaxEditorShowDiffs = function() { ajaxSetEditorLoading(); - var ta_content = $dynano('ajaxEditArea').getContent(); + var ta_content = ajaxEditorGetContent(); ta_content = ajaxEscape(ta_content); if ( $dynano('enano_editor_preview').object.innerHTML != '' ) { @@ -909,32 +939,24 @@ }); } -window.ajaxSetEditorMCE = function(confirmed) +window.ajaxSetEditorMCE = function() { if ( editor_loading ) return false; - if ( !confirmed ) + var len = 0; + for ( var i in editor_formats ) + { + len++; + } + + if ( len == 0 ) { miniPromptMessage({ - title: $lang.get('editor_msg_convert_confirm_title'), - message: $lang.get('editor_msg_convert_confirm_body'), + title: $lang.get('editor_msg_convert_no_plugins_title'), + message: $lang.get('editor_msg_convert_no_plugins_body'), buttons: [ { - color: 'blue', - text: $lang.get('editor_btn_graphical'), - style: { - fontWeight: 'bold' - }, - sprite: [ editor_img_path + '/sprite.png', 16, 16, 0, 112 ], - onclick: function() - { - ajaxSetEditorMCE(true); - miniPromptDestroy(this); - return false; - } - }, - { text: $lang.get('etc_cancel'), onclick: function() { @@ -947,14 +969,46 @@ return false; } - // Clear out existing buttons - var span_wiki = $dynano('enano_edit_btn_pt').object; - var span_mce = $dynano('enano_edit_btn_mce').object; - span_wiki.style.display = 'inline'; - span_mce.style.display = 'none'; + var mp = miniPrompt(function(div) + { + $(div).css('text-align', 'center'); + $(div).append('

' + $lang.get('editor_msg_convert_confirm_title') + '

'); + $(div).append('

' + $lang.get('editor_msg_convert_confirm_body') + '

'); + var select = ''; + + $(div).append('

' + $lang.get('editor_msg_convert_lbl_plugin') + select + '

'); + $(div).append('

' + gen_sprite_html(editor_img_path + '/sprite.png', 16, 16, 0, 112) + $lang.get('editor_btn_graphical_convert') + '' + + '' + $lang.get('etc_cancel') + '

'); + + $('a.go_action', div).click(function() + { + // go ahead with converting to this format + + var parent = miniPromptGetParent(this); + var whitey = whiteOutMiniPrompt(parent); + var plugin = $('select.format', parent).val(); + ajaxEditorSetFormat(plugin, function() + { + if ( typeof(whitey) == 'object' ) + whiteOutReportSuccess(whitey); + }); + return false; + }); + + $('a.cancel_action', div).click(function() + { + miniPromptDestroy(this); + return false; + }); + }); - // Swap editor - $dynano('ajaxEditArea').switchToMCE(true); + return false; } window.ajaxSetEditorPlain = function(confirmed) @@ -1002,7 +1056,20 @@ span_mce.style.display = 'inline'; // Swap editor - $dynano('ajaxEditArea').destroyMCE(true); + if ( typeof(editor_formats[window.page_format].ui_destroy) == 'function' ) + { + if ( typeof(editor_formats[window.page_format].convert_from) == 'function' ) + { + var text = ajaxEditorGetContent(); + var newtext = editor_formats[window.page_format].convert_from(text); + if ( typeof(newtext) != 'string' ) + newtext = text; + } + editor_formats[window.page_format].ui_destroy(); + $('#ajaxEditArea').val(newtext); + } + + window.page_format = 'wikitext'; } var editor_loading = false; @@ -1084,7 +1151,7 @@ var now = unix_time(); aed.as_last_save = now; - var ta_content = $dynano('ajaxEditArea').getContent(); + var ta_content = ajaxEditorGetContent(); if ( ta_content == '' || ta_content == '

' || ta_content == '

 

' || ta_content == editor_orig_text || ta_content == editor_last_draft ) { @@ -1125,7 +1192,22 @@ editor_convert_if_needed(response.page_format); - $dynano('ajaxEditArea').setContent(response.src); + if ( response.page_format != 'wikitext' && typeof(editor_formats[response.page_format]) == 'object' ) + { + if ( typeof(editor_formats[response.page_format].set_text) == 'function' ) + { + editor_formats[response.page_format].set_text(response.src); + } + else + { + $('#ajaxEditArea').val(response.src); + } + } + else + { + $('#ajaxEditArea').val(response.src); + } + $dynano('ajaxEditArea').object.used_draft = true; editor_orig_text = editor_last_draft = response.src; @@ -1144,12 +1226,12 @@ window.editor_convert_if_needed = function(targetformat, noticetitle, noticebody) { // Do we need to change the format? - var need_to_mce = ( targetformat == 'xhtml' && !$dynano('ajaxEditArea').isMCE() ); - var need_to_wkt = ( targetformat == 'wikitext' && $dynano('ajaxEditArea').isMCE() ); + var need_to_mce = ( targetformat != 'wikitext' && page_format == 'wikitext' ); + var need_to_wkt = ( targetformat == 'wikitext' && page_format != 'wikitext' ); if ( need_to_mce ) { - $dynano('ajaxEditArea').setContent(''); - $dynano('ajaxEditArea').switchToMCE(false); + editor_formats[targetformat].ui_construct(); + window.page_format = targetformat; // Clear out existing buttons var span_wiki = $dynano('enano_edit_btn_pt').object; @@ -1159,8 +1241,8 @@ } else if ( need_to_wkt ) { - $dynano('ajaxEditArea').setContent(''); - $dynano('ajaxEditArea').destroyMCE(false); + editor_formats[window.page_format].ui_construct(); + window.page_format = 'wikitext'; // Clear out existing buttons var span_wiki = $dynano('enano_edit_btn_pt').object; @@ -1192,3 +1274,51 @@ }); } } + +window.ajaxEditorSetFormat = function(plugin, success_func) + { + // perform conversion + if ( typeof(editor_formats[plugin].convert_to) == 'function' ) + { + var result = editor_formats[plugin].convert_to($('#ajaxEditArea').val()); + } + else + { + var result = $('#ajaxEditArea').val(); + } + if ( typeof(result) != 'string' ) + { + result = $('#ajaxEditArea').val(); + } + $('#ajaxEditArea').val(result); + if ( typeof(editor_formats[plugin].ui_construct) == 'function' ) + { + editor_formats[plugin].ui_construct(); + } + success_func(); + window.page_format = plugin; + + // change the buttons over + $('#enano_edit_btn_pt').css('display', 'inline'); + $('#enano_edit_btn_mce').css('display', 'none'); + }; + +window.ajaxEditorGetContent = function() + { + if ( window.page_format == 'wikitext' ) + { + return $('#ajaxEditArea').val(); + } + else + { + if ( typeof(editor_formats[window.page_format].get_text) == 'function' ) + { + return editor_formats[window.page_format].get_text(); + } + else + { + return $('#ajaxEditArea').val(); + } + } + }; + diff -r 2164d18cb10c -r 2a31905a567d includes/clientside/static/enano-lib-basic.js --- a/includes/clientside/static/enano-lib-basic.js Thu Jun 02 05:24:38 2011 -0400 +++ b/includes/clientside/static/enano-lib-basic.js Thu Jun 02 05:28:28 2011 -0400 @@ -43,7 +43,6 @@ var detect = navigator.userAgent.toLowerCase(); var IE; -var is_Safari; // Detect whether the user is running the Evil One or not... @@ -61,9 +60,12 @@ var is_Webkit = checkIt('applewebkit'); var is_Gecko = checkIt('gecko'); var is_firefox2 = checkIt('firefox/2.'); +var is_Safari = checkIt('safari') ? true : false; var KILL_SWITCH = false; +var editor_formats = {}; + if ( IE ) { var version = window.navigator.appVersion; @@ -92,8 +94,6 @@ var DISABLE_MCE = false; } -is_Safari = checkIt('safari') ? true : false; - var cmt_open; var editor_open = false; var list; diff -r 2164d18cb10c -r 2a31905a567d includes/common.php --- a/includes/common.php Thu Jun 02 05:24:38 2011 -0400 +++ b/includes/common.php Thu Jun 02 05:28:28 2011 -0400 @@ -46,7 +46,7 @@ // This is incremented each time a change to the database structure is made. // If it doesn't match the version in the DB, the user will be asked to upgrade. // This must match install/includes/common.php! -$db_version = 1125; +$db_version = 1126; /** * Returns a floating-point number with the current UNIX timestamp in microseconds. Defined very early because we gotta call it diff -r 2164d18cb10c -r 2a31905a567d includes/namespaces/default.php --- a/includes/namespaces/default.php Thu Jun 02 05:24:38 2011 -0400 +++ b/includes/namespaces/default.php Thu Jun 02 05:28:28 2011 -0400 @@ -426,16 +426,21 @@ if ( $incl_inner_headers ) { - if ( $page_format === 'wikitext' ) + if ( $page_format === 'wikitext' || !function_exists("render_text_{$page_format}") ) { $text = '?>' . RenderMan::render($text); } else { + $result = call_user_func("render_text_{$page_format}", $text); + if ( is_string($result) ) + { + $text = $result; + unset($result); + } // Page format is XHTML. This means we want to disable functionality that MCE takes care of, while still retaining // the ability to wikilink, the ability to use images, etc. Basically, RENDER_INLINEONLY disables all behavior in // the rendering engine/Text_Wiki that conflicts with MCE. - $text = '?>' . RenderMan::render($text, RENDER_INLINE); } } else diff -r 2164d18cb10c -r 2a31905a567d includes/pageprocess.php --- a/includes/pageprocess.php Thu Jun 02 05:24:38 2011 -0400 +++ b/includes/pageprocess.php Thu Jun 02 05:28:28 2011 -0400 @@ -366,12 +366,12 @@ * @param string The new text for the page * @param string A summary of edits made to the page. * @param bool If true, the edit is marked as a minor revision - * @param string Page format - wikitext or xhtml. REQUIRED, and new in 1.1.6. + * @param string Page format. New in 1.1.6; defaults to "wikitext" * @param array Optional - the entire incoming request. Plugins can add their own data to it. * @return bool True on success, false on failure. When returning false, it will push errors to the PageProcessor error stack; read with $page->pop_error() */ - function update_page($text, $edit_summary = false, $minor_edit = false, $page_format, $raw_request = array()) + function update_page($text, $edit_summary = false, $minor_edit = false, $page_format = 'wikitext', $raw_request = array()) { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; @@ -444,9 +444,10 @@ } // Page format check - if ( !in_array($page_format, array('xhtml', 'wikitext')) ) + $page_format = $db->escape($page_format); + if ( !preg_match('/^[a-z0-9_]+$/', $page_format) ) { - $this->raise_error("format \"$page_format\" not one of [xhtml, wikitext]"); + $this->raise_error('Page format must match /^[a-z0-9_]+$/'); return false; } diff -r 2164d18cb10c -r 2a31905a567d includes/render.php --- a/includes/render.php Thu Jun 02 05:24:38 2011 -0400 +++ b/includes/render.php Thu Jun 02 05:28:28 2011 -0400 @@ -241,7 +241,7 @@ { // inline only $carpenter->disable_all_rules(); - foreach ( array('bold', 'italic', 'underline', 'externalwithtext', 'externalnotext', 'image', 'internallink') as $rule ) + foreach ( array('heading', 'bold', 'italic', 'underline', 'externalwithtext', 'externalnotext', 'image', 'internallink') as $rule ) { $carpenter->enable_rule($rule); } diff -r 2164d18cb10c -r 2a31905a567d install/schemas/upgrade/mysql/1126.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/install/schemas/upgrade/mysql/1126.sql Thu Jun 02 05:28:28 2011 -0400 @@ -0,0 +1,2 @@ +UPDATE {{TABLE_PREFIX}}pages SET page_format = 'tinymce' WHERE page_format = 'xhtml'; + diff -r 2164d18cb10c -r 2a31905a567d install/schemas/upgrade/postgresql/1126.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/install/schemas/upgrade/postgresql/1126.sql Thu Jun 02 05:28:28 2011 -0400 @@ -0,0 +1,2 @@ +-- Postgres never did have a constraint on this column. +UPDATE {{TABLE_PREFIX}}pages SET page_format = 'tinymce' WHERE page_format = 'xhtml'; diff -r 2164d18cb10c -r 2a31905a567d language/english/core.json --- a/language/english/core.json Thu Jun 02 05:24:38 2011 -0400 +++ b/language/english/core.json Thu Jun 02 05:28:28 2011 -0400 @@ -387,10 +387,16 @@ msg_have_draft_body: '%author% saved a draft version of this page on %time%. You can use the draft copy, or edit the current published version (below). If you edit the published version, the draft copy will remain available, but will not reflect your changes. It is recommended that you edit the draft version instead of editing the published version. You can also discard the draft revision.', msg_convert_confirm_title: 'Convert this page?', msg_convert_confirm_body: 'This will change the format of the page. This may cause some loss of formatting information.', + msg_convert_no_plugins_title: 'Unable to convert page', + msg_convert_no_plugins_body: 'There are no editor UI plugins installed on this site.', + msg_convert_missing_plugin_title: 'Missing editor plugin', + msg_convert_missing_plugin_body: 'This page or revision was formatted using the plugin "%plugin%", which is no longer installed on the site. The plain text editor will be used. Some formatting information may not be correct.', msg_convert_draft_load_title: 'Format changed', msg_convert_draft_load_body: 'The revision that was just loaded is in a different format than the current setting. The editor has been switched to match the format.', - btn_graphical: 'Convert to HTML', - btn_wikitext: 'Convert to wikitext', + msg_convert_lbl_plugin: 'Editor plugin: ', + btn_graphical: 'Use another format', + btn_graphical_convert: 'Convert page', + btn_wikitext: 'Convert to plain text', lbl_edit_summary: 'Brief summary of your changes:', lbl_edit_summary_explain: 'Please summarize and briefly explain what you changed on the page.', lbl_minor_edit: 'Mark revision as trivial:', @@ -576,7 +582,7 @@ edit_comments: 'Edit own comments', edit_page: 'Edit page', view_source: 'View source', - edit_wysiwyg: 'Use graphical editor (WEAK)', + edit_wysiwyg: 'Use alternate editor engines (WEAK)', mod_comments: 'Moderate comments', history_view: 'View history/diffs', history_rollback: 'Rollback history',