Skip to content
This repository has been archived by the owner on Oct 30, 2018. It is now read-only.

Support separate groups metadata in loader #656

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions lib/app/addons/ac/deploy.server.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,26 +83,30 @@ YUI.add('mojito-deploy-addon', function(Y, NAME) {

fetchCSS: true,
combine: true,
base: "/combo?",
comboBase: "/combo?",
root: "",
url: "/combo?yui-base/yui-base.js&loader-base/loader-base.js&" +
"loader-app-base{langPath}.js"
// the base path for non-combo paths
base: 'http://yui.yahooapis.com/' + Y.version + '/build/',
// the path to the combo service
comboBase: 'http://yui.yahooapis.com/combo?',
// a fragment to prepend to the path attribute when
// when building combo urls
root: Y.version + '/build/',
seed: "/static/combo?yui-base.js&loader-base.js&" +
"loader-yui3.js&loader-app-base{langPath}.js&loader.js"

}, ((appConfigClient.yui && appConfigClient.yui.config) || {}), {
lang: contextServer.lang // same as contextClient.lang
});

// adjusting the url based on {langPath} to facilitate
// adjusting the seed based on {langPath} to facilitate
// the customization of the combo url.
yuiConfig.url = yuiConfig.url.replace('{langPath}',
yuiConfig.seed = yuiConfig.seed.replace('{langPath}',
(contextServer.lang ? '_' + contextServer.lang : ''));

clientConfig.store = store.serializeClientStore(contextClient);

// Set the YUI URL to use on the client (This has to be done
// before any other scripts are added)
assetHandler.addAsset('js', 'top', yuiConfig.url);
assetHandler.addAsset('js', 'top', yuiConfig.seed);

// adding the default module for the Y.use statement in the client
initialModuleList['mojito-client'] = true;
Expand Down
196 changes: 127 additions & 69 deletions lib/app/middleware/mojito-combo-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@

/*jslint anon:true, sloppy:true, nomen:true, stupid:true, node: true*/

'use strict';

/*
DECLAIMER: this is VERY experimental, and the purpose of this
middleware is to provide an easy way to load yui modules by their
names rather than the real static path. Why? because we can then
leverage the YUI Loader on the client side to take care of the
dependencies computations efficiently.
names rather than the real static path.
from: @caridy
*/

Expand Down Expand Up @@ -60,18 +60,52 @@ var libfs = require('fs'),
}
},

// This dummy templace will be use to produce the loader content.
// TODO: we should use YUI.applyConfig() instead of the internal
// YUI.Env API, but that's pending due a bug in YUI:
// http://yuilibrary.com/projects/yui3/ticket/2532854
LOADER_MODULE_TEMPLATE = 'YUI.add("loader",function(Y){' +
'YUI.Env[Y.version].modules=YUI.Env[Y.version].modules||{metadata};' +
'}, "", {requires:["loader-base"]});';

/*
* File buffer cache.
*/
var _cache = {};
MODULE_TEMPLATES = {
'loader-app-base':
'YUI.add("loader-app-base",function(Y){' +
'Y.applyConfig({groups:{app:{' +
'combine:true,' +
'maxURLLength:1024,' +
'base:"/static/",' +
'comboBase:"/static/combo?",' +
'root:"",' +
'modules:{app-base}' +
'}}});' +
'},"",{requires:["loader-base"]});',
'loader-app-full':
'YUI.add("loader-app-full",function(Y){' +
'Y.applyConfig({groups:{app:{' +
'combine:true,' +
'maxURLLength:1024,' +
'base:"/static/",' +
'comboBase:"/static/combo?",' +
'root:"",' +
'modules:{app-full}' +
'}}});' +
'},"",{requires:["loader-base"]});',

'loader':
'YUI.add("loader",function(Y){' +
'},"",{requires:["loader-base","loader-yui3","loader-app-base"]});',

'loader-lock':
'YUI.add("loader",function(Y){' +
// TODO: we should use YUI.applyConfig() instead of the internal
// YUI.Env API, but that's pending due a bug in YUI:
// http://yuilibrary.com/projects/yui3/ticket/2532854
'YUI.Env[Y.version].modules=YUI.Env[Y.version].modules||' +
'{yui-base};' +
'},"",{requires:["loader-base","loader-app-base"]});',

'loader-full':
'YUI.add("loader",function(Y){' +
// TODO: we should use YUI.applyConfig() instead of the internal
// YUI.Env API, but that's pending due a bug in YUI:
// http://yuilibrary.com/projects/yui3/ticket/2532854
'YUI.Env[Y.version].modules=YUI.Env[Y.version].modules||' +
'{yui-full};' +
'},"",{requires:["loader-base","loader-app-full"]});'
};

/*
* Check if `req` and response `headers`.
Expand Down Expand Up @@ -167,20 +201,6 @@ function forbidden(res) {
res.end(body);
}

/*
* Clear the memory cache for `key` or the entire cache.
*
* @method clearCache
* @param {String} key
* @api public
*/
function clearCache(key) {
if (key) {
delete _cache[key];
} else {
_cache = {};
}
}

function processMeta(resolvedMods, modules, expanded_modules, langs, conditions) {
var m,
Expand Down Expand Up @@ -247,25 +267,6 @@ function processMeta(resolvedMods, modules, expanded_modules, langs, conditions)
}


function produceMeta(meta, name) {
var token = '',
path = '',
lang = REGEX_LOCALE.exec(name);

if (lang && lang[1] && meta[lang[1]]) {
lang = lang[1]; // eg. en-US
token = '"' + lang + '"';
path = '_' + lang;
meta = meta[lang];
} else {
meta = meta['*']; // default in case they use invalid lang
}
return LOADER_MODULE_TEMPLATE
.replace('{metadata}', meta)
.replace(REGEX_LANG_TOKEN, token)
.replace(REGEX_LANG_PATH, path);
}

/*
* Static file server.
*
Expand Down Expand Up @@ -296,8 +297,15 @@ function staticProvider(store, globalLogger) {
Y,
loader,
resolved,
appMetaData = {},
appResolvedMetaData = {},

appMetaData = {
base: {},
full: {}
},
yuiMetaData = {
base: {},
full: {}
},

// other structures
langs = ['*'], // language wildcard
Expand All @@ -312,14 +320,14 @@ function staticProvider(store, globalLogger) {
Y = YUI({
fetchCSS: true,
combine: true,
base: "/combo?",
comboBase: "/combo?",
base: "/static/combo?",
comboBase: "/static/combo?",
root: ""
}, ((appConfig.yui && appConfig.yui.config && appConfig.yui.config.config) || {}));

modules_config = Y.merge((mojits.modules || {}), (shared.modules || {}));
Y.applyConfig({
modules: modules_config,
modules: Y.merge({}, modules_config),
useSync: true
});
Y.use('loader');
Expand All @@ -342,8 +350,10 @@ function staticProvider(store, globalLogger) {
for (i = 0; i < langs.length; i += 1) {
lang = langs[i];

appMetaData[lang] = {};
appResolvedMetaData[lang] = {};
appMetaData.base[lang] = {};
appMetaData.full[lang] = {};
yuiMetaData.base[lang] = {};
yuiMetaData.full[lang] = {};

for (name in expanded_modules) {
if (expanded_modules.hasOwnProperty(name)) {
Expand All @@ -359,28 +369,63 @@ function staticProvider(store, globalLogger) {
(!expanded_modules[name].langPack) ||
(lang === expanded_modules[name].langPack)) {

appMetaData[lang][name] = modules[name];
appResolvedMetaData[lang][name] = expanded_modules[name];
// we want to separate modules into different buckets
// to be able to support groups in loader config
if (modules_config[name]) {
appMetaData.base[lang][name] = modules[name];
appMetaData.full[lang][name] = expanded_modules[name];
} else {
yuiMetaData.base[lang][name] = modules[name];
yuiMetaData.full[lang][name] = expanded_modules[name];
}

}
}
}

appMetaData[lang] = JSON.stringify(appMetaData[lang]);
appResolvedMetaData[lang] = JSON.stringify(appResolvedMetaData[lang]);
appMetaData.base[lang] = JSON.stringify(appMetaData.base[lang]);
appMetaData.full[lang] = JSON.stringify(appMetaData.full[lang]);
yuiMetaData.base[lang] = JSON.stringify(yuiMetaData.base[lang]);
yuiMetaData.full[lang] = JSON.stringify(yuiMetaData.full[lang]);

for (name in conditions) {
if (conditions.hasOwnProperty(name)) {
appMetaData[lang] = appMetaData[lang]
appMetaData.base[lang] = appMetaData.base[lang]
.replace('"{' + name + '}"', conditions[name]);
appResolvedMetaData[lang] = appResolvedMetaData[lang]
appMetaData.full[lang] = appMetaData.full[lang]
.replace('"{' + name + '}"', conditions[name]);
yuiMetaData.base[lang] = yuiMetaData.base[lang]
.replace('"{' + name + '}"', conditions[name]);
yuiMetaData.full[lang] = yuiMetaData.full[lang]
.replace('"{' + name + '}"', conditions[name]);
}
}

}


function produceMeta(name, lang) {
var token = '',
path = '';

if (lang) {
token = '"' + lang + '"';
path = '_' + lang;
} else {
lang = '*';
}

// module definition definitions
return MODULE_TEMPLATES[name]
.replace('{app-base}', appMetaData.base[lang] || appMetaData.base['*'])
.replace('{app-full}', appMetaData.full[lang] || appMetaData.full['*'])
.replace('{yui-base}', yuiMetaData.base[lang] || yuiMetaData.base['*'])
.replace('{yui-full}', yuiMetaData.full[lang] || yuiMetaData.full['*'])
.replace(REGEX_LANG_TOKEN, token)
.replace(REGEX_LANG_PATH, path);
}


return function(req, res, next) {
if (req.method !== 'GET' && req.method !== 'HEAD') {
return next();
Expand All @@ -390,6 +435,8 @@ function staticProvider(store, globalLogger) {
files = [],
filename = '',
module = '',
basemodule = '',
lang = '',
ext = '',
result = [],
counter = 0,
Expand All @@ -398,7 +445,7 @@ function staticProvider(store, globalLogger) {
head = (req.method === 'HEAD');

// only combo requests are allow here
if (url.pathname !== '/combo' || !url.query) {
if (libpath.basename(url.pathname) !== 'combo' || !url.query) {
return next();
}

Expand Down Expand Up @@ -468,22 +515,33 @@ function staticProvider(store, globalLogger) {
module = (files[i].indexOf('/lang/') >= 0 ? 'lang/' : '') +
libpath.basename(files[i], ext).replace(/\-(min|debug)$/, '');

if (module.indexOf('loader-app-base') === 0) {
result[i] = {
fullpath: module,
content: produceMeta(appMetaData, module)
};
} else if (module.indexOf('loader-app-full') === 0) {
lang = REGEX_LOCALE.exec(module);

if (lang) {
basemodule = module.slice(0, lang.index); // eg. lang/foo_en-US -> lang/foo
lang = lang[1];
} else {
basemodule = module;
}

// at this point, we should have:
// module == lang/foo_en-US or lang/foo or foo
// basemodule == lang/foo or foo

if (MODULE_TEMPLATES[basemodule]) {
// getting a synthetic module
result[i] = {
fullpath: module,
content: produceMeta(appResolvedMetaData, module)
content: produceMeta(basemodule, lang)
};
} else if (urls[module]) {
// geting an app module
result[i] = {
fullpath: urls[module],
content: ''
};
} else if (loader.moduleInfo[module] && loader.moduleInfo[module].path) {
// getting a yui module
result[i] = {
fullpath: libpath.join(__dirname,
'../../../node_modules/yui', loader.moduleInfo[module].path),
Expand Down