diff --git a/package.json b/package.json index 04ee8c12c3..4d819ab281 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "validator": "~3.16.1", "winston": "~0.7.2", "xregexp": "~2.0.0", - "templates.js": "0.0.9" + "templates.js": "0.0.10" }, "devDependencies": { "mocha": "~1.13.0" diff --git a/public/src/forum/admin/themes.js b/public/src/forum/admin/themes.js index c76fea0c9a..6a1b3db477 100644 --- a/public/src/forum/admin/themes.js +++ b/public/src/forum/admin/themes.js @@ -1,5 +1,5 @@ "use strict"; -/*global define, socket, app, bootbox, tabIndent, config, RELATIVE_PATH*/ +/*global define, socket, app, bootbox, tabIndent, config, RELATIVE_PATH, templates */ define('forum/admin/themes', ['forum/admin/settings'], function(Settings) { var Themes = {}; @@ -71,17 +71,17 @@ define('forum/admin/themes', ['forum/admin/settings'], function(Settings) { if (confirm) { socket.emit('admin.themes.set', { type: 'local', - id: 'nodebb-theme-cerulean' + id: 'nodebb-theme-vanilla' }, function(err) { if (err) { return app.alertError(err.message); } - highlightSelectedTheme('nodebb-theme-cerulean'); + highlightSelectedTheme('nodebb-theme-vanilla'); app.alert({ alert_id: 'admin:theme', type: 'success', title: 'Theme Changed', - message: 'You have successfully reverted your NodeBB back to it\'s default theme. Restarting your NodeBB ', + message: 'You have successfully reverted your NodeBB back to it\'s default theme.', timeout: 3500 }); }); @@ -95,34 +95,19 @@ define('forum/admin/themes', ['forum/admin/settings'], function(Settings) { return app.alertError(err.message); } - var instListEl = $('#installed_themes').empty(), liEl; + var instListEl = $('#installed_themes'); if (!themes.length) { instListEl.append($('
  • ').addClass('no-themes').html('No installed themes found')); return; + } else { + templates.parse('partials/admin/theme_list', { + themes: themes + }, function(html) { + instListEl.html(html); + highlightSelectedTheme(config['theme:id']); + }); } - - for (var x = 0, numThemes = themes.length; x < numThemes; x++) { - liEl = $('
  • ').attr({ - 'data-type': 'local', - 'data-theme': themes[x].id - }).html('' + - '
    ' + - '
    ' + - ' ' + - '
    ' + - '

    ' + themes[x].name + '

    ' + - '

    ' + - themes[x].description + - (themes[x].url ? ' (Homepage)' : '') + - '

    ' + - '
    ' + - '
    '); - - instListEl.append(liEl); - } - - highlightSelectedTheme(config['theme:id']); }); // Proper tabbing for "Custom CSS" field @@ -138,26 +123,23 @@ define('forum/admin/themes', ['forum/admin/settings'], function(Settings) { }; Themes.render = function(bootswatch) { - var themeContainer = $('#bootstrap_themes').empty(), - numThemes = bootswatch.themes.length, themeEl, theme; - - for (var x = 0; x < numThemes; x++) { - theme = bootswatch.themes[x]; - themeEl = $('
  • ').attr({ - 'data-type': 'bootswatch', - 'data-css': theme.cssCdn, - 'data-theme': theme.name - }).html('' + - '
    ' + - '
    ' + - ' ' + - '
    ' + - '

    ' + theme.name + '

    ' + - '

    ' + theme.description + '

    ' + - '
    ' + - '
    '); - themeContainer.append(themeEl); - } + var themeContainer = $('#bootstrap_themes'); + + templates.parse('partials/admin/theme_list', { + themes: bootswatch.themes.map(function(theme) { + return { + type: 'bootswatch', + id: theme.name, + name: theme.name, + description: theme.description, + screenshot_url: theme.thumbnail, + url: theme.preview, + css: theme.cssCdn + }; + }) + }, function(html) { + themeContainer.html(html); + }); }; Themes.prepareWidgets = function() { diff --git a/public/src/templates.js b/public/src/templates.js index 5cf10aeb4b..fc81b14e29 100644 --- a/public/src/templates.js +++ b/public/src/templates.js @@ -36,7 +36,7 @@ Please use the npm module instead - require('templates.js') } callback(parse(loaded, obj, bind)); - }); + }); } else { callback(parse(templates.cache[template], obj, bind)); } @@ -58,14 +58,15 @@ Please use the npm module instead - require('templates.js') }; templates.getBlock = function(template, block) { - return template.replace(new RegExp('[\\s\\S]*([\r\n]*[\\s\\S]*?[\r\n]*)[\\s\\S]*', 'g'), '$1'); + return template.replace(new RegExp('[\\s\\S]*([\\s\\S]*?)[\\s\\S]*', 'g'), '$1'); }; function express(filename, options, fn) { - console.log(filename, options, fn); var fs = require('fs'), tpl = filename.replace(options.settings.views + '/', ''); + options['_locals'] = null; + if (!templates.cache[tpl]) { fs.readFile(filename, function(err, html) { templates.cache[tpl] = (html || '').toString(); @@ -82,11 +83,11 @@ Please use the npm module instead - require('templates.js') } function makeRegex(block) { - return new RegExp('[\\s\\S]*?'); + return new RegExp('[\\t ]*[\\s\\S]*?'); } function makeBlockRegex(block) { - return new RegExp('([\\n]?[\\n]?)|([\\n]?[\\n]?)', 'g'); + return new RegExp('([\\t ]*[\\r\\n?|\\n]?)|()', 'g'); } function makeConditionalRegex(block) { @@ -94,7 +95,7 @@ Please use the npm module instead - require('templates.js') } function makeStatementRegex(key) { - return new RegExp('([\\s]*)|([\\s]*)', 'gi'); + return new RegExp('([\\s]*)|([\\s]*)', 'g'); } function registerGlobals(obj) { @@ -113,23 +114,23 @@ Please use the npm module instead - require('templates.js') if (matches !== null) { for (var i = 0, ii = matches.length; i < ii; i++) { var statement = makeStatementRegex(key), - nestedConditionals = matches[i].match(/[\s|\S][\s|\S]/), - match = matches[i].replace(statement, '').replace(/[\s|\S][\s|\S]/gi, ''), - conditionalBlock = match.split(/\s*\s*/); + nestedConditionals = matches[i].match(/(?!^)(?!$)/), + match = matches[i].replace(statement, '').replace(/(?!^)/gi, ''), + conditionalBlock = match.split(/[\r\n?\n]*?[\r\n?\n]*?/); if (conditionalBlock[1]) { // there is an else statement - if (!value) { - template = template.replace(matches[i], conditionalBlock[1].replace(/(^[\r\n\t]*)|([\r\n\t]*$)/gi, '')); + if (!value) { // todo check second line break conditional, doesn't match. + template = template.replace(matches[i], conditionalBlock[1].replace(/(^[\r\n?|\n]*)|([\r\n\t]*$)/gi, '')); } else { - template = template.replace(matches[i], conditionalBlock[0].replace(/(^[\r\n\t]*)|([\r\n\t]*$)/gi, '')); + template = template.replace(matches[i], conditionalBlock[0].replace(/(^[\r\n?|\n]*)|([\r\n\t]*$)/gi, '')); } } else { // regular if statement if (!value) { template = template.replace(matches[i], ''); } else { - template = template.replace(matches[i], match.replace(/(^[\r\n\t]*)|([\r\n\t]*$)/gi, '')); + template = template.replace(matches[i], match.replace(/(^[\r\n?|\n]*)|([\r\n\t]*$)/gi, '')); } } @@ -181,40 +182,43 @@ Please use the npm module instead - require('templates.js') var regex = makeRegex(key), block; if (!array[key].length) { - return template; + return template.replace(regex, ''); } while (block = template.match(regex)) { block = block[0].replace(makeBlockRegex(key), ''); - + var numblocks = array[key].length - 1, iterator = 0, result = '', parsedBlock; do { - parsedBlock = parse(block, array[key][iterator], bind, namespace, {iterator: iterator, total: numblocks}) + ((iterator < numblocks) ? '\r\n':''); - + parsedBlock = parse(block, array[key][iterator], bind, namespace, {iterator: iterator, total: numblocks}); + result += (!bind) ? parsedBlock : setBindContainer(parsedBlock, bind + namespace + iterator); - result = parseFunctions(block, result, { - data: array[key][iterator], - iterator: iterator, - numblocks: numblocks - }); result = checkConditional(result, '@first', iterator === 0); result = checkConditional(result, '!@first', iterator !== 0); result = checkConditional(result, '@last', iterator === numblocks); result = checkConditional(result, '!@last', iterator !== numblocks); + result = result.replace(/^[\r\n?|\n|\t]*?|[\r\n?|\n|\t]*?$/g, ''); + + result = parseFunctions(block, result, { + data: array[key][iterator], + iterator: iterator, + numblocks: numblocks + }); + if (bind) { array[key][iterator].__template = block; } } while (iterator++ < numblocks); - template = template.replace(regex, result); + template = template.replace(regex, result.replace(/^[\r\n?|\n]|[\r\n?|\n]$/g, '')); } - + return template; } @@ -248,14 +252,14 @@ Please use the npm module instead - require('templates.js') this['__' + key] = value; var els = document.querySelectorAll('[data-binding="' + (this.__iterator !== false ? (bind + this.__namespace + this.__iterator) : bind) + '"]'); - + for (var el in els) { if (els.hasOwnProperty(el)) { if (this.__parent) { var parent = this.__parent(); els[el].innerHTML = parse(parent.template, parent.data, false); } else { - els[el].innerHTML = parse(this.__template, obj, false, this.__namespace); + els[el].innerHTML = parse(this.__template, obj, false, this.__namespace); } } } @@ -295,7 +299,7 @@ Please use the npm module instead - require('templates.js') template = parse(template, obj[key], bind, namespace + key + '.'); } else { template = parseValue(template, namespace + key, obj[key]); - + if (bind && obj[key]) { setupBindings({ obj: obj, diff --git a/src/meta/themes.js b/src/meta/themes.js index b26253a495..f41620cc1b 100644 --- a/src/meta/themes.js +++ b/src/meta/themes.js @@ -39,6 +39,15 @@ module.exports = function(Meta) { return next(); } else { var configObj = JSON.parse(file.toString()); + + // Minor adjustments for API output + configObj.type = 'local'; + if (configObj.screenshot) { + configObj.screenshot_url = nconf.get('relative_path') + '/css/previews/' + configObj.id + } else { + configObj.screenshot_url = nconf.get('relative_path') + '/images/themes/default.png'; + } + next(err, configObj); } });