diff --git a/applications/admin/controllers/default.py b/applications/admin/controllers/default.py index a23ea5c2..490fa907 100644 --- a/applications/admin/controllers/default.py +++ b/applications/admin/controllers/default.py @@ -561,11 +561,11 @@ def edit(): # Load json only if it is ajax edited... app = get_app(request.vars.app) - if not(request.ajax): + if not(request.ajax): # return the scaffolding, the rest will be through ajax requests response.title = T('Editing %s' % app) editarea_preferences = {} - editarea_preferences['FONT_SIZE'] = '10' + editarea_preferences['FONT_SIZE'] = '10' editarea_preferences['FULL_SCREEN'] = 'false' editarea_preferences['ALLOW_TOGGLE'] = 'true' editarea_preferences['REPLACE_TAB_BY_SPACES'] = '4' @@ -574,7 +574,7 @@ def edit(): if key in globals(): editarea_preferences[key] = globals()[key] return response.render ('default/edit.html', dict(app=request.args[0], editarea_preferences=editarea_preferences)) - + """ File edit handler """ # Load json only if it is ajax edited... app = get_app(request.vars.app) @@ -722,7 +722,7 @@ def edit(): vf = os.path.split(v)[-1] vargs = "/".join([viewpath.replace(os.sep, "/"), vf]) editviewlinks.append(A(vf.split(".")[0], - _class="editor_filelink", + _class="editor_filelink", _href=URL('edit', args=[vargs]))) if len(request.args) > 2 and request.args[1] == 'controllers': @@ -746,11 +746,11 @@ def edit(): view_link=view_link, editviewlinks=editviewlinks, id=IS_SLUG()(filename)[0], - force= True if (request.vars.restore or request.vars.revert) else False) + force= True if (request.vars.restore or request.vars.revert) else False) plain_html = response.render('default/edit_js.html', file_details) file_details['plain_html'] = plain_html return response.json(file_details) - + def resolve(): """ @@ -1770,4 +1770,3 @@ def git_push(): session.flash = T("Push failed, there are unmerged entries in the cache. Resolve merge issues manually and try again.") redirect(URL('site')) return dict(app=app, form=form) - diff --git a/applications/admin/languages/it.py b/applications/admin/languages/it.py index 98bc43b6..6a4973cb 100644 --- a/applications/admin/languages/it.py +++ b/applications/admin/languages/it.py @@ -8,6 +8,7 @@ '%Y-%m-%d': '%d/%m/%Y', '%Y-%m-%d %H:%M:%S': '%d/%m/%Y %H:%M:%S', '(requires internet access)': '(requires internet access)', +'(requires internet access, experimental)': '(requires internet access, experimental)', '(something like "it-it")': '(qualcosa simile a "it-it")', '@markmin\x01(file **gluon/contrib/plural_rules/%s.py** is not found)': '(file **gluon/contrib/plural_rules/%s.py** is not found)', '@markmin\x01Searching: **%s** %%{file}': 'Searching: **%s** files', @@ -43,6 +44,7 @@ 'ATTENTION: Login requires a secure (HTTPS) connection or running on localhost.': "ATTENZIONE: L'accesso richiede una connessione sicura (HTTPS) o l'esecuzione di web2py in locale (connessione su localhost)", 'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ATTENTZIONE: NON ESEGUIRE PIÙ TEST IN PARALLELO (I TEST NON SONO "THREAD SAFE")', 'ATTENTION: you cannot edit the running application!': "ATTENZIONE: non puoi modificare l'applicazione correntemente in uso ", +'Autocomplete Python Code': 'Autocomplete Python Code', 'Available databases and tables': 'Database e tabelle disponibili', 'back': 'indietro', 'cache': 'cache', @@ -113,10 +115,12 @@ 'Edit': 'modifica', 'Edit application': 'Modifica applicazione', 'edit controller': 'modifica controller', +'edit controller:': 'edit controller:', 'Edit current record': 'Modifica record corrente', 'edit profile': 'modifica profilo', 'Edit This App': 'Modifica questa applicazione', 'edit views:': 'modifica viste (view):', +'Editing bigul': 'Editing bigul', 'Editing file "%s"': 'Modifica del file "%s"', 'Editing Language file': 'Modifica file linguaggio', 'Enterprise Web Framework': 'Enterprise Web Framework', @@ -140,6 +144,8 @@ 'file saved on %(time)s': "file salvato nell'istante %(time)s", 'file saved on %s': 'file salvato: %s', 'filter': 'filter', +'Find Next': 'Find Next', +'Find Previous': 'Find Previous', 'Frames': 'Frames', 'Functions with no doctests will result in [passed] tests.': 'I test delle funzioni senza "doctests" risulteranno sempre [passed].', 'Get from URL:': 'Get from URL:', @@ -177,15 +183,16 @@ 'License for': 'Licenza relativa a', 'loading...': 'caricamento...', 'locals': 'locals', -'login': 'accesso', 'Login': 'Accesso', +'login': 'accesso', 'Login to the Administrative Interface': "Accesso all'interfaccia amministrativa", 'Logout': 'uscita', 'Main Menu': 'Menu principale', +'Manage': 'Manage', 'Menu Model': 'Menu Modelli', 'merge': 'unisci', -'models': 'modelli', 'Models': 'Modelli', +'models': 'modelli', 'Modules': 'Moduli', 'modules': 'moduli', 'new application "%s" created': 'creata la nuova applicazione "%s"', @@ -198,6 +205,7 @@ 'NO': 'NO', 'No databases in this application': 'Nessun database presente in questa applicazione', 'no match': 'nessuna corrispondenza', +'online designer': 'online designer', 'or alternatively': 'or alternatively', 'Or Get from URL:': 'Or Get from URL:', 'or import from csv file': 'oppure importa da file CSV', @@ -206,6 +214,7 @@ 'Overwrite installed app': 'sovrascrivi applicazione installata', 'Pack all': 'crea pacchetto', 'Pack compiled': 'crea pacchetto del codice compilato', +'Pack custom': 'Pack custom', 'pack plugin': 'crea pacchetto del plugin', 'PAM authenticated user, cannot change password here': 'utente autenticato tramite PAM, impossibile modificare password qui', 'password changed': 'password modificata', @@ -217,15 +226,19 @@ 'Plural-Forms:': 'Plural-Forms:', 'Powered by': 'Powered by', 'previous 100 rows': '100 righe precedenti', -'private files': 'private files', 'Private files': 'Private files', +'private files': 'private files', 'Query:': 'Richiesta (query):', +'Rapid Search': 'Rapid Search', 'record': 'record', 'record does not exist': 'il record non esiste', 'record id': 'ID del record', 'register': 'registrazione', 'reload': 'reload', +'Reload routes': 'Reload routes', 'Remove compiled': 'rimozione codice compilato', +'Replace': 'Replace', +'Replace All': 'Replace All', 'request': 'request', 'Resolve Conflict file': 'File di risoluzione conflitto', 'response': 'response', @@ -237,6 +250,8 @@ "Run tests in this file (to run all files, you may also use the button labelled 'test')": "Run tests in this file (to run all files, you may also use the button labelled 'test')", 'Running on %s': 'Running on %s', 'Save': 'Save', +'Save file:': 'Save file:', +'Save file: %s': 'Save file: %s', 'Save via Ajax': 'Save via Ajax', 'Saved file hash:': 'Hash del file salvato:', 'selected': 'selezionato', @@ -245,23 +260,24 @@ 'shell': 'shell', 'Site': 'sito', 'some files could not be removed': 'non è stato possibile rimuovere alcuni files', +'Start searching': 'Start searching', 'Start wizard': 'start wizard', 'state': 'stato', 'static': 'statico', 'Static': 'Static', 'Static files': 'Files statici', 'Stylesheet': 'Foglio di stile (stylesheet)', -'submit': 'invia', 'Submit': 'Submit', +'submit': 'invia', 'Sure you want to delete this object?': 'Vuoi veramente cancellare questo oggetto?', 'table': 'tabella', 'test': 'test', 'Testing application': 'Test applicazione in corsg', 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'La richiesta (query) è una condizione come ad esempio "db.tabella1.campo1==\'valore\'". Una condizione come "db.tabella1.campo1==db.tabella2.campo2" produce un "JOIN" SQL.', -'The application logic, each URL path is mapped in one exposed function in the controller': 'The application logic, each URL path is mapped in one exposed function in the controller', 'the application logic, each URL path is mapped in one exposed function in the controller': 'logica dell\'applicazione, ogni percorso "URL" corrisponde ad una funzione esposta da un controller', -'The data representation, define database tables and sets': 'The data representation, define database tables and sets', +'The application logic, each URL path is mapped in one exposed function in the controller': 'The application logic, each URL path is mapped in one exposed function in the controller', 'the data representation, define database tables and sets': 'rappresentazione dei dati, definizione di tabelle di database e di "set" ', +'The data representation, define database tables and sets': 'The data representation, define database tables and sets', 'The presentations layer, views are also known as templates': 'The presentations layer, views are also known as templates', 'the presentations layer, views are also known as templates': 'Presentazione dell\'applicazione, viste (views, chiamate anche "templates")', 'There are no controllers': 'Non ci sono controller', @@ -273,8 +289,8 @@ 'There are no translators, only default language is supported': 'Non ci sono traduzioni, viene solo supportato il linguaggio di base', 'There are no views': 'Non ci sono viste ("view")', 'These files are not served, they are only available from within your app': 'These files are not served, they are only available from within your app', -'these files are served without processing, your images go here': 'questi files vengono serviti così come sono, le immagini vanno qui', 'These files are served without processing, your images go here': 'These files are served without processing, your images go here', +'these files are served without processing, your images go here': 'questi files vengono serviti così come sono, le immagini vanno qui', 'This is the %(filename)s template': 'Questo è il template %(filename)s', 'Ticket': 'Ticket', 'Ticket ID': 'Ticket ID', @@ -322,8 +338,8 @@ 'Version %s.%s.%s (%s) %s': 'Version %s.%s.%s (%s) %s', 'versioning': 'sistema di versioni', 'Versioning': 'Versioning', -'view': 'vista', 'View': 'Vista', +'view': 'vista', 'Views': 'viste', 'views': 'viste', 'Web Framework': 'Web Framework', diff --git a/applications/admin/static/js/ajax_editor.js b/applications/admin/static/js/ajax_editor.js index 9f3fca87..e23b3481 100644 --- a/applications/admin/static/js/ajax_editor.js +++ b/applications/admin/static/js/ajax_editor.js @@ -1,262 +1,281 @@ -function prepareDataForSave(name,data) { - var obj = new Object(); - obj.Name = name; - obj.Data = data; - return obj; +function prepareDataForSave(name, data) { + var obj = new Object(); + obj.Name = name; + obj.Data = data; + return obj; } function prepareMultiPartPOST(data) { - // var boundary = 'sPlItME' + Math.floor(Math.random()*10000); - var boundary = '' + Math.floor(Math.random()*10000); - var reqdata = '--' + boundary + '\r\n'; - //console.log(data.length); - for (var i=0;i < data.length;i++) { - reqdata += 'content-disposition: form-data; name="'; - reqdata += data[i].Name + '"'; - reqdata += "\r\n\r\n" ; - reqdata += data[i].Data; - reqdata += "\r\n" ; - reqdata += '--' + boundary + '\r\n'; - } - return new Array(reqdata,boundary); + // var boundary = 'sPlItME' + Math.floor(Math.random()*10000); + var boundary = '' + Math.floor(Math.random() * 10000); + var reqdata = '--' + boundary + '\r\n'; + //console.log(data.length); + for(var i = 0; i < data.length; i++) { + reqdata += 'content-disposition: form-data; name="'; + reqdata += data[i].Name + '"'; + reqdata += "\r\n\r\n"; + reqdata += data[i].Data; + reqdata += "\r\n"; + reqdata += '--' + boundary + '\r\n'; + } + return new Array(reqdata, boundary); } function on_error() { - jQuery("input[name='saved_on']").attr('style','background-color:red'); - jQuery("input[name='saved_on']").val('communication error'); + jQuery("input[name='saved_on']").attr('style', 'background-color:red'); + jQuery("input[name='saved_on']").val('communication error'); } function doHighlight(highlight) { - // Put the cursor at the offending line: - editor.setCursor({line:highlight.lineno-1, - ch:highlight.offset+1}); - } + // Put the cursor at the offending line: + editor.setCursor({ + line: highlight.lineno - 1, + ch: highlight.offset + 1 + }); +} function doClickSave() { - var currentTabID = '#' + jQuery('#edit_placeholder div.tab-pane.active').attr('id'); - var editor = jQuery (currentTabID + ' textarea').data('editor'); - var data = editor.getValue(); - var dataForPost = prepareMultiPartPOST(new Array( - prepareDataForSave('data', data), - prepareDataForSave('file_hash', - jQuery(currentTabID + " input[name='file_hash']").val()), - prepareDataForSave('saved_on', - jQuery(currentTabID + " input[name='saved_on']").val()), - prepareDataForSave('saved_on', - jQuery(currentTabID + " input[name='saved_on']").val()), - prepareDataForSave('from_ajax','true'))); - // console.info(area.textarea.value); - jQuery(currentTabID + " input[name='saved_on']").attr('style', - 'background-color:yellow'); - jQuery(currentTabID + " input[name='saved_on']").val('saving now...') - currentUrl = jQuery(currentTabID + ' form').attr('action'); - jQuery.ajax({ - type: "POST", - contentType: 'multipart/form-data;boundary="' - + dataForPost[1] + '"', - url: currentUrl, - dataType: "json", - data: dataForPost[0], - timeout: 5000, - beforeSend: function(xhr) { - xhr.setRequestHeader('web2py-component-location', - document.location); - xhr.setRequestHeader('web2py-component-element', - 'doClickSave'); - }, - success: function(json,text,xhr){ - jQuery(editor).data('saved', true); // Set as saved - editor.on("change", store_changes_function); // Re-enable change watcher - // reenable disabled submit button - var t=jQuery("input[name='save']"); - t.attr('class',''); - t.attr('disabled',''); - try { - if (json.error) { - window.location.href=json.redirect; - } else { - // console.info( json.file_hash ); - jQuery(currentTabID + " input[name='file_hash']").val(json.file_hash); - jQuery(currentTabID + " input[name='saved_on']").val(json.saved_on); - if (json.highlight) { - doHighlight(json.highlight); - } else { - jQuery(currentTabID + " input[name='saved_on']").attr('style','background-color:#99FF99'); - //jQuery(".flash").delay(1000).fadeOut('slow'); - } - // console.info(jQuery("input[name='file_hash']").val()); - var output = 'exposes: '; - for ( var i in json.functions) { - output += ' ' + json.functions[i] + ','; - } - if(output!='exposes: ') { - jQuery(currentTabID + " .exposed").html( output.substring(0, output.length-1)); - } - } - } catch(e) { on_error();} - }, - error: function(json) { on_error(); } - }); - return false; + var currentTabID = '#' + jQuery('#edit_placeholder div.tab-pane.active').attr('id'); + var editor = jQuery(currentTabID + ' textarea').data('editor'); + var data = editor.getValue(); + var dataForPost = prepareMultiPartPOST(new Array( + prepareDataForSave('data', data), + prepareDataForSave('file_hash', + jQuery(currentTabID + " input[name='file_hash']").val()), + prepareDataForSave('saved_on', + jQuery(currentTabID + " input[name='saved_on']").val()), + prepareDataForSave('saved_on', + jQuery(currentTabID + " input[name='saved_on']").val()), + prepareDataForSave('from_ajax', 'true'))); + // console.info(area.textarea.value); + jQuery(currentTabID + " input[name='saved_on']").attr('style', + 'background-color:yellow'); + jQuery(currentTabID + " input[name='saved_on']").val('saving now...') + currentUrl = jQuery(currentTabID + ' form').attr('action'); + jQuery.ajax({ + type: "POST", + contentType: 'multipart/form-data;boundary="' + dataForPost[1] + '"', + url: currentUrl, + dataType: "json", + data: dataForPost[0], + timeout: 5000, + beforeSend: function (xhr) { + xhr.setRequestHeader('web2py-component-location', + document.location); + xhr.setRequestHeader('web2py-component-element', + 'doClickSave'); + }, + success: function (json, text, xhr) { + jQuery(editor).data('saved', true); // Set as saved + editor.on("change", store_changes_function); // Re-enable change watcher + // reenable disabled submit button + var t = jQuery("input[name='save']"); + t.attr('class', ''); + t.attr('disabled', ''); + try { + if(json.error) { + window.location.href = json.redirect; + } else { + // console.info( json.file_hash ); + jQuery(currentTabID + " input[name='file_hash']").val(json.file_hash); + jQuery(currentTabID + " input[name='saved_on']").val(json.saved_on); + if(json.highlight) { + doHighlight(json.highlight); + } else { + jQuery(currentTabID + " input[name='saved_on']").attr('style', 'background-color:#99FF99'); + //jQuery(".flash").delay(1000).fadeOut('slow'); + } + // console.info(jQuery("input[name='file_hash']").val()); + var output = 'exposes: '; + for(var i in json.functions) { + output += ' ' + json.functions[i] + ','; + } + if(output != 'exposes: ') { + jQuery(currentTabID + " .exposed").html(output.substring(0, output.length - 1)); + } + } + } catch(e) { + on_error(); + } + }, + error: function (json) { + on_error(); + } + }); + return false; } function getActiveEditor() { - var currentTabID = '#' + jQuery('#edit_placeholder div.tab-pane.active').attr('id'); - var editor = jQuery (currentTabID + ' textarea').data('editor'); - return editor; + var currentTabID = '#' + jQuery('#edit_placeholder div.tab-pane.active').attr('id'); + var editor = jQuery(currentTabID + ' textarea').data('editor'); + return editor; } function getSelectionRange() { - var editor = getActiveEditor(); - var sel = {}; - sel['start'] = editor.getCursor(true).line; - sel['end'] = editor.getCursor(false).line; - sel['data'] = ''; - return sel; + var editor = getActiveEditor(); + var sel = {}; + sel['start'] = editor.getCursor(true).line; + sel['end'] = editor.getCursor(false).line; + sel['data'] = ''; + return sel; } function doToggleBreakpoint(filename, url, sel) { - var editor = getActiveEditor(); - if (sel==null) { - // use cursor position to determine the breakpoint line - // (gutter already tell us the selected line) - sel = getSelectionRange(); + var editor = getActiveEditor(); + if(sel == null) { + // use cursor position to determine the breakpoint line + // (gutter already tell us the selected line) + sel = getSelectionRange(); + } + var dataForPost = prepareMultiPartPOST(new Array( + prepareDataForSave('filename', filename), + prepareDataForSave('sel_start', sel["start"]), + prepareDataForSave('sel_end', sel["end"]), + prepareDataForSave('data', sel['data']))); + jQuery.ajax({ + type: "POST", + contentType: 'multipart/form-data;boundary="' + dataForPost[1] + '"', + url: url, + dataType: "json", + data: dataForPost[0], + timeout: 5000, + beforeSend: function (xhr) { + xhr.setRequestHeader('web2py-component-location', + document.location); + xhr.setRequestHeader('web2py-component-element', + 'doSetBreakpoint'); + }, + success: function (json, text, xhr) { + // show flash message (if any) + var flash = xhr.getResponseHeader('web2py-component-flash'); + if(flash) { + jQuery('.flash').html(decodeURIComponent(flash)) + .append('×') + .slideDown(); + } else jQuery('.flash').hide(); + try { + if(json.error) { + window.location.href = json.redirect; + } else { + if(json.ok == true) { + // mark the breakpoint if ok=True + editor.setGutterMarker(json.lineno - 1, "breakpoints", makeMarker()); + } else if(json.ok == false) { + // remove mark if ok=False + editor.setGutterMarker(json.lineno - 1, "breakpoints", null); + } + } + } catch(e) { + on_error(); + } + }, + error: function (json) { + on_error(); } - var dataForPost = prepareMultiPartPOST(new Array( - prepareDataForSave('filename', filename), - prepareDataForSave('sel_start', sel["start"]), - prepareDataForSave('sel_end', sel["end"]), - prepareDataForSave('data', sel['data']))); - jQuery.ajax({ - type: "POST", - contentType: 'multipart/form-data;boundary="'+dataForPost[1]+'"', - url: url, - dataType: "json", - data: dataForPost[0], - timeout: 5000, - beforeSend: function(xhr) { - xhr.setRequestHeader('web2py-component-location', - document.location); - xhr.setRequestHeader('web2py-component-element', - 'doSetBreakpoint');}, - success: function(json,text,xhr){ - // show flash message (if any) - var flash=xhr.getResponseHeader('web2py-component-flash'); - if (flash) { - jQuery('.flash').html(decodeURIComponent(flash)) - .append('×') - .slideDown(); - } - else jQuery('.flash').hide(); - try { - if (json.error) { - window.location.href=json.redirect; - } else { - if (json.ok==true) { - // mark the breakpoint if ok=True - editor.setGutterMarker(json.lineno-1, "breakpoints", makeMarker()); - } else if (json.ok==false) { - // remove mark if ok=False - editor.setGutterMarker(json.lineno-1, "breakpoints", null); - } - } - } catch(e) { on_error(); } - }, - error: function(json) { on_error(); } - }); - return false; + }); + return false; } // on load, update all breakpoints markers: + function doListBreakpoints(filename, url, editor) { - var dataForPost = prepareMultiPartPOST(new Array( - prepareDataForSave('filename', filename) - )); - jQuery.ajax({ - type: "POST", - contentType: 'multipart/form-data;boundary="'+dataForPost[1]+'"', - url: url, - dataType: "json", - data: dataForPost[0], - timeout: 5000, - beforeSend: function(xhr) { - xhr.setRequestHeader('web2py-component-location', - document.location); - xhr.setRequestHeader('web2py-component-element', - 'doListBreakpoints');}, - success: function(json,text,xhr){ - try { - if (json.error) { - window.location.href=json.redirect; - } else { - var editor = getActiveEditor(); - for (i in json.breakpoints) { - lineno = json.breakpoints[i]; - // mark the breakpoint if ok=True - editor.setGutterMarker(lineno-1, "breakpoints",makeMarker()); - } - } - } catch(e) { on_error(); } - }, - error: function(json) { on_error(); } - }); - return false; + var dataForPost = prepareMultiPartPOST(new Array( + prepareDataForSave('filename', filename) + )); + jQuery.ajax({ + type: "POST", + contentType: 'multipart/form-data;boundary="' + dataForPost[1] + '"', + url: url, + dataType: "json", + data: dataForPost[0], + timeout: 5000, + beforeSend: function (xhr) { + xhr.setRequestHeader('web2py-component-location', + document.location); + xhr.setRequestHeader('web2py-component-element', + 'doListBreakpoints'); + }, + success: function (json, text, xhr) { + try { + if(json.error) { + window.location.href = json.redirect; + } else { + var editor = getActiveEditor(); + for(i in json.breakpoints) { + lineno = json.breakpoints[i]; + // mark the breakpoint if ok=True + editor.setGutterMarker(lineno - 1, "breakpoints", makeMarker()); + } + } + } catch(e) { + on_error(); + } + }, + error: function (json) { + on_error(); + } + }); + return false; } - function makeMarker() { - var marker = document.createElement("div"); - marker.style.color = "#822"; - marker.innerHTML = "●"; - marker.className = "breakpoint"; - return marker; - } +function makeMarker() { + var marker = document.createElement("div"); + marker.style.color = "#822"; + marker.innerHTML = "●"; + marker.className = "breakpoint"; + return marker; +} function keepalive(url) { - jQuery.ajax({ - type: "GET", - url: url, - timeout: 1000, - success: function(){}, - error: function(x) { on_error(); } }); + jQuery.ajax({ + type: "GET", + url: url, + timeout: 1000, + success: function () {}, + error: function (x) { + on_error(); + } + }); } -function load_file (url) { - jQuery.ajax({ - type: "GET", - dataType: 'json', - url: url, - timeout: 1000, - success: function(json){ - if (typeof(json['plain_html']) !== undefined) { - if (jQuery('#' + json['id']).length === 0 || json['force'] === true) { - // Create a tab and put the code in it - var tab_header = '
{{{a_tag}}}
{{address}}'; - diff --git a/applications/admin/static/js/hogan-2.0.0.js b/applications/admin/static/js/hogan-2.0.0.js index 43a67074..a278dbd4 100644 --- a/applications/admin/static/js/hogan-2.0.0.js +++ b/applications/admin/static/js/hogan-2.0.0.js @@ -12,565 +12,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - - -var Hogan = {}; - -(function (Hogan, useArrayBuffer) { - Hogan.Template = function (renderFunc, text, compiler, options) { - this.r = renderFunc || this.r; - this.c = compiler; - this.options = options; - this.text = text || ''; - this.buf = (useArrayBuffer) ? [] : ''; - } - - Hogan.Template.prototype = { - // render: replaced by generated code. - r: function (context, partials, indent) { return ''; }, - - // variable escaping - v: hoganEscape, - - // triple stache - t: coerceToString, - - render: function render(context, partials, indent) { - return this.ri([context], partials || {}, indent); - }, - - // render internal -- a hook for overrides that catches partials too - ri: function (context, partials, indent) { - return this.r(context, partials, indent); - }, - - // tries to find a partial in the curent scope and render it - rp: function(name, context, partials, indent) { - var partial = partials[name]; - - if (!partial) { - return ''; - } - - if (this.c && typeof partial == 'string') { - partial = this.c.compile(partial, this.options); - } - - return partial.ri(context, partials, indent); - }, - - // render a section - rs: function(context, partials, section) { - var tail = context[context.length - 1]; - - if (!isArray(tail)) { - section(context, partials, this); - return; - } - - for (var i = 0; i < tail.length; i++) { - context.push(tail[i]); - section(context, partials, this); - context.pop(); - } - }, - - // maybe start a section - s: function(val, ctx, partials, inverted, start, end, tags) { - var pass; - - if (isArray(val) && val.length === 0) { - return false; - } - - if (typeof val == 'function') { - val = this.ls(val, ctx, partials, inverted, start, end, tags); - } - - pass = (val === '') || !!val; - - if (!inverted && pass && ctx) { - ctx.push((typeof val == 'object') ? val : ctx[ctx.length - 1]); - } - - return pass; - }, - - // find values with dotted names - d: function(key, ctx, partials, returnFound) { - var names = key.split('.'), - val = this.f(names[0], ctx, partials, returnFound), - cx = null; - - if (key === '.' && isArray(ctx[ctx.length - 2])) { - return ctx[ctx.length - 1]; - } - - for (var i = 1; i < names.length; i++) { - if (val && typeof val == 'object' && names[i] in val) { - cx = val; - val = val[names[i]]; - } else { - val = ''; - } - } - - if (returnFound && !val) { - return false; - } - - if (!returnFound && typeof val == 'function') { - ctx.push(cx); - val = this.lv(val, ctx, partials); - ctx.pop(); - } - - return val; - }, - - // find values with normal names - f: function(key, ctx, partials, returnFound) { - var val = false, - v = null, - found = false; - - for (var i = ctx.length - 1; i >= 0; i--) { - v = ctx[i]; - if (v && typeof v == 'object' && key in v) { - val = v[key]; - found = true; - break; - } - } - - if (!found) { - return (returnFound) ? false : ""; - } - - if (!returnFound && typeof val == 'function') { - val = this.lv(val, ctx, partials); - } - - return val; - }, - - // higher order templates - ho: function(val, cx, partials, text, tags) { - var compiler = this.c; - var options = this.options; - options.delimiters = tags; - var text = val.call(cx, text); - text = (text == null) ? String(text) : text.toString(); - this.b(compiler.compile(text, options).render(cx, partials)); - return false; - }, - - // template result buffering - b: (useArrayBuffer) ? function(s) { this.buf.push(s); } : - function(s) { this.buf += s; }, - fl: (useArrayBuffer) ? function() { var r = this.buf.join(''); this.buf = []; return r; } : - function() { var r = this.buf; this.buf = ''; return r; }, - - // lambda replace section - ls: function(val, ctx, partials, inverted, start, end, tags) { - var cx = ctx[ctx.length - 1], - t = null; - - if (!inverted && this.c && val.length > 0) { - return this.ho(val, cx, partials, this.text.substring(start, end), tags); - } - - t = val.call(cx); - - if (typeof t == 'function') { - if (inverted) { - return true; - } else if (this.c) { - return this.ho(t, cx, partials, this.text.substring(start, end), tags); - } - } - - return t; - }, - - // lambda replace variable - lv: function(val, ctx, partials) { - var cx = ctx[ctx.length - 1]; - var result = val.call(cx); - - if (typeof result == 'function') { - result = coerceToString(result.call(cx)); - if (this.c && ~result.indexOf("{\u007B")) { - return this.c.compile(result, this.options).render(cx, partials); - } - } - - return coerceToString(result); - } - - }; - - var rAmp = /&/g, - rLt = //g, - rApos =/\'/g, - rQuot = /\"/g, - hChars =/[&<>\"\']/; - - - function coerceToString(val) { - return String((val === null || val === undefined) ? '' : val); - } - - function hoganEscape(str) { - str = coerceToString(str); - return hChars.test(str) ? - str - .replace(rAmp,'&') - .replace(rLt,'<') - .replace(rGt,'>') - .replace(rApos,''') - .replace(rQuot, '"') : - str; - } - - var isArray = Array.isArray || function(a) { - return Object.prototype.toString.call(a) === '[object Array]'; - }; - -})(typeof exports !== 'undefined' ? exports : Hogan); - - - - -(function (Hogan) { - // Setup regex assignments - // remove whitespace according to Mustache spec - var rIsWhitespace = /\S/, - rQuot = /\"/g, - rNewline = /\n/g, - rCr = /\r/g, - rSlash = /\\/g, - tagTypes = { - '#': 1, '^': 2, '/': 3, '!': 4, '>': 5, - '<': 6, '=': 7, '_v': 8, '{': 9, '&': 10 - }; - - Hogan.scan = function scan(text, delimiters) { - var len = text.length, - IN_TEXT = 0, - IN_TAG_TYPE = 1, - IN_TAG = 2, - state = IN_TEXT, - tagType = null, - tag = null, - buf = '', - tokens = [], - seenTag = false, - i = 0, - lineStart = 0, - otag = '{{', - ctag = '}}'; - - function addBuf() { - if (buf.length > 0) { - tokens.push(new String(buf)); - buf = ''; - } - } - - function lineIsWhitespace() { - var isAllWhitespace = true; - for (var j = lineStart; j < tokens.length; j++) { - isAllWhitespace = - (tokens[j].tag && tagTypes[tokens[j].tag] < tagTypes['_v']) || - (!tokens[j].tag && tokens[j].match(rIsWhitespace) === null); - if (!isAllWhitespace) { - return false; - } - } - - return isAllWhitespace; - } - - function filterLine(haveSeenTag, noNewLine) { - addBuf(); - - if (haveSeenTag && lineIsWhitespace()) { - for (var j = lineStart, next; j < tokens.length; j++) { - if (!tokens[j].tag) { - if ((next = tokens[j+1]) && next.tag == '>') { - // set indent to token value - next.indent = tokens[j].toString() - } - tokens.splice(j, 1); - } - } - } else if (!noNewLine) { - tokens.push({tag:'\n'}); - } - - seenTag = false; - lineStart = tokens.length; - } - - function changeDelimiters(text, index) { - var close = '=' + ctag, - closeIndex = text.indexOf(close, index), - delimiters = trim( - text.substring(text.indexOf('=', index) + 1, closeIndex) - ).split(' '); - - otag = delimiters[0]; - ctag = delimiters[1]; - - return closeIndex + close.length - 1; - } - - if (delimiters) { - delimiters = delimiters.split(' '); - otag = delimiters[0]; - ctag = delimiters[1]; - } - - for (i = 0; i < len; i++) { - if (state == IN_TEXT) { - if (tagChange(otag, text, i)) { - --i; - addBuf(); - state = IN_TAG_TYPE; - } else { - if (text.charAt(i) == '\n') { - filterLine(seenTag); - } else { - buf += text.charAt(i); - } - } - } else if (state == IN_TAG_TYPE) { - i += otag.length - 1; - tag = tagTypes[text.charAt(i + 1)]; - tagType = tag ? text.charAt(i + 1) : '_v'; - if (tagType == '=') { - i = changeDelimiters(text, i); - state = IN_TEXT; - } else { - if (tag) { - i++; - } - state = IN_TAG; - } - seenTag = i; - } else { - if (tagChange(ctag, text, i)) { - tokens.push({tag: tagType, n: trim(buf), otag: otag, ctag: ctag, - i: (tagType == '/') ? seenTag - ctag.length : i + otag.length}); - buf = ''; - i += ctag.length - 1; - state = IN_TEXT; - if (tagType == '{') { - if (ctag == '}}') { - i++; - } else { - cleanTripleStache(tokens[tokens.length - 1]); - } - } - } else { - buf += text.charAt(i); - } - } - } - - filterLine(seenTag, true); - - return tokens; - } - - function cleanTripleStache(token) { - if (token.n.substr(token.n.length - 1) === '}') { - token.n = token.n.substring(0, token.n.length - 1); - } - } - - function trim(s) { - if (s.trim) { - return s.trim(); - } - - return s.replace(/^\s*|\s*$/g, ''); - } - - function tagChange(tag, text, index) { - if (text.charAt(index) != tag.charAt(0)) { - return false; - } - - for (var i = 1, l = tag.length; i < l; i++) { - if (text.charAt(index + i) != tag.charAt(i)) { - return false; - } - } - - return true; - } - - function buildTree(tokens, kind, stack, customTags) { - var instructions = [], - opener = null, - token = null; - - while (tokens.length > 0) { - token = tokens.shift(); - if (token.tag == '#' || token.tag == '^' || isOpener(token, customTags)) { - stack.push(token); - token.nodes = buildTree(tokens, token.tag, stack, customTags); - instructions.push(token); - } else if (token.tag == '/') { - if (stack.length === 0) { - throw new Error('Closing tag without opener: /' + token.n); - } - opener = stack.pop(); - if (token.n != opener.n && !isCloser(token.n, opener.n, customTags)) { - throw new Error('Nesting error: ' + opener.n + ' vs. ' + token.n); - } - opener.end = token.i; - return instructions; - } else { - instructions.push(token); - } - } - - if (stack.length > 0) { - throw new Error('missing closing tag: ' + stack.pop().n); - } - - return instructions; - } - - function isOpener(token, tags) { - for (var i = 0, l = tags.length; i < l; i++) { - if (tags[i].o == token.n) { - token.tag = '#'; - return true; - } - } - } - - function isCloser(close, open, tags) { - for (var i = 0, l = tags.length; i < l; i++) { - if (tags[i].c == close && tags[i].o == open) { - return true; - } - } - } - - Hogan.generate = function (tree, text, options) { - var code = 'var _=this;_.b(i=i||"");' + walk(tree) + 'return _.fl();'; - if (options.asString) { - return 'function(c,p,i){' + code + ';}'; - } - - return new Hogan.Template(new Function('c', 'p', 'i', code), text, Hogan, options); - } - - function esc(s) { - return s.replace(rSlash, '\\\\') - .replace(rQuot, '\\\"') - .replace(rNewline, '\\n') - .replace(rCr, '\\r'); - } - - function chooseMethod(s) { - return (~s.indexOf('.')) ? 'd' : 'f'; - } - - function walk(tree) { - var code = ''; - for (var i = 0, l = tree.length; i < l; i++) { - var tag = tree[i].tag; - if (tag == '#') { - code += section(tree[i].nodes, tree[i].n, chooseMethod(tree[i].n), - tree[i].i, tree[i].end, tree[i].otag + " " + tree[i].ctag); - } else if (tag == '^') { - code += invertedSection(tree[i].nodes, tree[i].n, - chooseMethod(tree[i].n)); - } else if (tag == '<' || tag == '>') { - code += partial(tree[i]); - } else if (tag == '{' || tag == '&') { - code += tripleStache(tree[i].n, chooseMethod(tree[i].n)); - } else if (tag == '\n') { - code += text('"\\n"' + (tree.length-1 == i ? '' : ' + i')); - } else if (tag == '_v') { - code += variable(tree[i].n, chooseMethod(tree[i].n)); - } else if (tag === undefined) { - code += text('"' + esc(tree[i]) + '"'); - } - } - return code; - } - - function section(nodes, id, method, start, end, tags) { - return 'if(_.s(_.' + method + '("' + esc(id) + '",c,p,1),' + - 'c,p,0,' + start + ',' + end + ',"' + tags + '")){' + - '_.rs(c,p,' + - 'function(c,p,_){' + - walk(nodes) + - '});c.pop();}'; - } - - function invertedSection(nodes, id, method) { - return 'if(!_.s(_.' + method + '("' + esc(id) + '",c,p,1),c,p,1,0,0,"")){' + - walk(nodes) + - '};'; - } - - function partial(tok) { - return '_.b(_.rp("' + esc(tok.n) + '",c,p,"' + (tok.indent || '') + '"));'; - } - - function tripleStache(id, method) { - return '_.b(_.t(_.' + method + '("' + esc(id) + '",c,p,0)));'; - } - - function variable(id, method) { - return '_.b(_.v(_.' + method + '("' + esc(id) + '",c,p,0)));'; - } - - function text(id) { - return '_.b(' + id + ');'; - } - - Hogan.parse = function(tokens, text, options) { - options = options || {}; - return buildTree(tokens, '', [], options.sectionTags || []); - }, - - Hogan.cache = {}; - - Hogan.compile = function(text, options) { - // options - // - // asString: false (default) - // - // sectionTags: [{o: '_foo', c: 'foo'}] - // An array of object with o and c fields that indicate names for custom - // section tags. The example above allows parsing of {{_foo}}{{/foo}}. - // - // delimiters: A string that overrides the default delimiters. - // Example: "<% %>" - // - options = options || {}; - - var key = text + '||' + !!options.asString; - - var t = this.cache[key]; - - if (t) { - return t; - } - - t = this.generate(this.parse(this.scan(text, options.delimiters), text, options), text, options); - return this.cache[key] = t; - }; -})(typeof exports !== 'undefined' ? exports : Hogan); - +var Hogan={};(function(a,b){function i(a){return String(a===null||a===undefined?"":a)}function j(a){return a=i(a),h.test(a)?a.replace(c,"&").replace(d,"<").replace(e,">").replace(f,"'").replace(g,"""):a}a.Template=function(a,c,d,e){this.r=a||this.r,this.c=d,this.options=e,this.text=c||"",this.buf=b?[]:""},a.Template.prototype={r:function(a,b,c){return""},v:j,t:i,render:function(b,c,d){return this.ri([b],c||{},d)},ri:function(a,b,c){return this.r(a,b,c)},rp:function(a,b,c,d){var e=c[a];return e?(this.c&&typeof e=="string"&&(e=this.c.compile(e,this.options)),e.ri(b,c,d)):""},rs:function(a,b,c){var d=a[a.length-1];if(!k(d)){c(a,b,this);return}for(var e=0;e