From ea49ef806b3f9c6a0e7e82508f551cd2d48043ae Mon Sep 17 00:00:00 2001 From: Eston Bond Date: Mon, 3 Jan 2011 16:48:42 -0800 Subject: [PATCH] Fail nicely with a malformed language definition, play by Crockford's rules --- .../javascript/gollum-editor/gollum.editor.js | 116 ++++++++++-------- 1 file changed, 68 insertions(+), 48 deletions(-) diff --git a/lib/gollum/frontend/public/javascript/gollum-editor/gollum.editor.js b/lib/gollum/frontend/public/javascript/gollum-editor/gollum.editor.js index d1401280..9f63a3b8 100755 --- a/lib/gollum/frontend/public/javascript/gollum-editor/gollum.editor.js +++ b/lib/gollum/frontend/public/javascript/gollum-editor/gollum.editor.js @@ -107,11 +107,12 @@ * Used by the definitions in langs/ to register language definitions. */ $.GollumEditor.defineLanguage = function( language_name, languageObject ) { - if ( typeof languageObject == 'object' ) + if ( typeof languageObject == 'object' ) { LanguageDefinition.define( language_name, languageObject ); - else - debug('GollumEditor.defineLanguage: definition for ' + language_name - + ' is not an object'); + } else { + debug('GollumEditor.defineLanguage: definition for ' + language_name + + ' is not an object'); + } }; @@ -123,8 +124,8 @@ * @return void */ var debug = function(m) { - if ( ActiveOptions.Debug - && typeof console != 'undefined' ) { + if ( ActiveOptions.Debug && + typeof console != 'undefined' ) { console.log( m ); } }; @@ -164,15 +165,19 @@ LanguageDefinition.loadFor( name, function(x, t) { if ( t != 'success' ) { debug('Failed to load language definition for ' + name); + // well, fake it and turn everything off for this one + LanguageDefinition.define( name, {} ); return; } // update features that rely on the language definition - if ( EditorHas.functionBar() ) + if ( EditorHas.functionBar() ) { FunctionBar.refresh(); + } - if ( LanguageDefinition.isValid() && EditorHas.formatSelector() ) + if ( LanguageDefinition.isValid() && EditorHas.formatSelector() ) { FormatSelector.updateSelected(); + } } ); } else { @@ -236,11 +241,14 @@ * @return boolean */ isLoadedFor: function( markup_name ) { - if ( LanguageDefinition._LOADED_LANGS.length == 0 ) return false; + if ( LanguageDefinition._LOADED_LANGS.length === 0 ) { + return false; + } for ( var i=0; i < LanguageDefinition._LOADED_LANGS.length; i++ ) { - if ( LanguageDefinition._LOADED_LANGS[i] == markup_name ) - return true; + if ( LanguageDefinition._LOADED_LANGS[i] == markup_name ) { + return true; + } } return false; }, @@ -406,8 +414,9 @@ $(this).click( FunctionBar.evtFunctionButtonClick ); $(this).removeClass('disabled'); } - else if ( $(this).attr('id') != 'function-help' ) + else if ( $(this).attr('id') != 'function-help' ) { $(this).addClass('disabled'); + } }); // show bar as active @@ -458,7 +467,7 @@ // execute a replacement function if one exists if ( definitionObject.exec && typeof definitionObject.exec == 'function' ) { - definitionObject.exec ( txt, selText, $('#gollum-editor-body') ); + definitionObject.exec( txt, selText, $('#gollum-editor-body') ); return; } @@ -487,11 +496,11 @@ // remove any excess backreferences from the replace string rt = rt.replace( /\$[\d]/g, '' ); repText = rt; - } else if ( repText == '' ) { + } else if ( repText === '' ) { debug('Search string is empty'); // find position of $1 - this is where we will place the cursor - var cursor = rt.indexOf('$1'); + cursor = rt.indexOf('$1'); // we have an empty string, so just remove backreferences repText = rt.replace( /\$[\d]/g, '' ); @@ -513,9 +522,10 @@ repText += definitionObject.append; } - if ( repText ) + if ( repText ) { FunctionBar.replaceFieldSelection( $('#gollum-editor-body'), repText, reselect, cursor ); + } }, @@ -536,22 +546,25 @@ start = el.selectionStart; end = el.selectionEnd; } else { - var range = document.selection.createRange(); - var stored_range = range.duplicate(); - stored_range.moveToElementText( el ); - stored_range.setEndPoint( 'EndToEnd', range ); - start = stored_range.text.length - range.text.length; - end = start + range.text.length; - - // so, uh, we're close, but we need to search for line breaks and - // adjust the start/end points accordingly since IE counts them as - // 2 characters in TextRange. - var s = start; - var lb = 0; - debug('IE: start position is currently ' + s); - for ( var i=0; i < s; i++ ) - if ( el.value.charAt(i).match(/\r/) ) - ++lb; + var range = document.selection.createRange(); + var stored_range = range.duplicate(); + stored_range.moveToElementText( el ); + stored_range.setEndPoint( 'EndToEnd', range ); + start = stored_range.text.length - range.text.length; + end = start + range.text.length; + + // so, uh, we're close, but we need to search for line breaks and + // adjust the start/end points accordingly since IE counts them as + // 2 characters in TextRange. + var s = start; + var lb = 0; + var i; + debug('IE: start position is currently ' + s); + for ( i=0; i < s; i++ ) { + if ( el.value.charAt(i).match(/\r/) ) { + ++lb; + } + } if ( lb ) { debug('IE start: compensating for ' + lb + ' line breaks'); @@ -560,10 +573,12 @@ } var e = end; - for ( var i=0; i < e; i++ ) - if ( el.value.charAt(i).match(/\r/) ) - ++lb; - + for ( i=0; i < e; i++ ) { + if ( el.value.charAt(i).match(/\r/) ) { + ++lb; + } + } + if ( lb ) { debug('IE end: compensating for ' + lb + ' line breaks'); end = end - lb; @@ -592,8 +607,8 @@ if ( $field.length ) { selPos = FunctionBar.getFieldSelectionPosition( $field ); selStr = $field.val().substring( selPos.start, selPos.end ); - debug('Selected: ' + selStr + ' (' + selPos.start + ', ' - + selPos.end + ')'); + debug('Selected: ' + selStr + ' (' + selPos.start + ', ' + + selPos.end + ')'); return selStr; } return false; @@ -609,8 +624,9 @@ if ( LanguageDefinition.isValid() ) { $('#gollum-editor-function-bar a.function-button').unbind('click'); FunctionBar.activate(); - if ( Help ) + if ( Help ) { Help.setActiveHelp( LanguageDefinition.getActiveLanguage() ); + } } else { debug('Language definition is invalid.'); if ( FunctionBar.isShown() ) { @@ -639,7 +655,7 @@ var fullStr = $field.val(); var selectNew = true; if ( reselect === false) { - var selectNew = false; + selectNew = false; } var scrollTop = null; @@ -819,12 +835,14 @@ // go go inefficient algorithm for ( var i=0; i < helpData.length; i++ ) { - if ( typeof helpData[i] != 'object' ) break; + if ( typeof helpData[i] != 'object' ) { + break; + } var $newLi = $('
  • ' + helpData[i].menuName + '
  • '); $('#gollum-editor-help-parent').append( $newLi ); - if ( i == 0 ) { + if ( i === 0 ) { // select on first run $newLi.children('a').addClass('selected'); } @@ -851,7 +869,9 @@ $('#gollum-editor-help-list').html(''); $('#gollum-editor-help-content').html(''); for ( var i=0; i < subData.content.length; i++ ) { - if ( typeof subData.content[i] != 'object' ) break; + if ( typeof subData.content[i] != 'object' ) { + break; + } var $subLi = $('
  • ' + subData.content[i].menuName + '
  • '); @@ -986,8 +1006,8 @@ */ evtHelpButtonClick: function( e ) { e.preventDefault(); - if ( Help.isShown() ) Help.hide(); - else Help.show(); + if ( Help.isShown() ) { Help.hide(); } + else { Help.show(); } }, @@ -1003,7 +1023,7 @@ evtParentMenuClick: function( e ) { e.preventDefault(); // short circuit if we've selected this already - if ( $(this).hasClass('selected') ) return; + if ( $(this).hasClass('selected') ) { return; } // populate from help data for this var helpIndex = $(this).attr('rel'); @@ -1026,7 +1046,7 @@ */ evtSubMenuClick: function( e ) { e.preventDefault(); - if ( $(this).hasClass('selected') ) return; + if ( $(this).hasClass('selected') ) { return; } // split index rel data var rawIndex = $(this).attr('rel').split(':'); @@ -1044,7 +1064,7 @@ $.GollumEditor.Dialog = $.GollumDialog; $.GollumEditor.replaceSelection = function( repText ) { FunctionBar.replaceFieldSelection( $('#gollum-editor-body'), repText ); - } + }; // Placeholder exists as its own thing now $.GollumEditor.Placeholder = $.GollumPlaceholder;