lib/configuration/sort.js
function sort(taskInfo, rawConfig, parentConfig, optionalSchema) {
	var schema, subTaskConfigs, taskConfig, value;

	schema = optionalSchema || {};
	from(schema).to(taskInfo).imply(TASK_SCHEMA_MAPPINGS);
	schema = defaults({}, schema, SCHEMA_DEFAULTS);

	taskConfig = rawConfig;
	// NOTE: If schema provided, try to normalize properties inside 'config' property.
	if (optionalSchema) {
		taskConfig = regulate(taskConfig, ['config']);
	}
	taskConfig = normalize(schema, taskConfig, {
		before: before,
		after: after
	});
	taskConfig = renamePatternProperties(taskConfig);
	// NOTE: A thought about that `config` should be "normalized".
	// But remember that the `config` and `$` property prefix are designed for tasks that have no schemas.
	// It just won't do anything try to normalize it without schema.
	taskConfig = regulate(taskConfig, ['config']);

	// NOTE: When there is `plugin`,  `task`, `series` or `parallel` property,
	// then all other properties will be treated as properties, not sub-task configs.
	// So user don't have to use `config` keyword or `$` prefix.
	value = _.omit(rawConfig, Object.keys(taskConfig).concat('config'));
	if (!optionalSchema && (taskInfo.plugin || taskInfo.task || taskInfo.series || taskInfo.parallel)) {
		taskConfig = defaults(taskConfig, value);
	} else {
		subTaskConfigs = value;
	}

	// inherit parent's config
	taskConfig = defaults(taskConfig, parentConfig);

	return {
		taskInfo: taskInfo,
		taskConfig: taskConfig,
		subTaskConfigs: subTaskConfigs
	};

	function before(propSchema, values) {
		if (propSchema.type === 'glob') {
			_.defaults(propSchema, glob.SCHEMA);
		} else if (propSchema.type === 'path') {
			_.defaults(propSchema, path.SCHEMA);
		}
	}

	function after(propSchema, resolved) {
		var value, join;

		if (resolved) {
			value = resolved();

			if (propSchema.type === 'glob') {
				join = propSchema.properties.options.properties.join.default || 'src';
				return resolve(resolveSrc(parentConfig, value, join));
			} else if (propSchema.type === 'path') {
				join = propSchema.properties.options.properties.join.default || 'dest';
				return resolve(resolveDest(parentConfig, value, join));
			}
		}

		return resolved;

		function resolve(value) {
			return function () {
				return value;
			};
		}
	}
}
function sort(taskInfo, rawConfig, parentConfig, optionalSchema) {
	var schema, subTaskConfigs, taskConfig, value;

	schema = optionalSchema || {};
	from(schema).to(taskInfo).imply(TASK_SCHEMA_MAPPINGS);
	schema = defaults({}, schema, SCHEMA_DEFAULTS);

	taskConfig = rawConfig;
	// NOTE: If schema provided, try to normalize properties inside 'config' property.
	if (optionalSchema) {
		taskConfig = regulate(taskConfig, ['config']);
	}
	taskConfig = normalize(schema, taskConfig, {
		before: before,
		after: after
	});
	taskConfig = renamePatternProperties(taskConfig);
	// NOTE: A thought about that `config` should be "normalized".
	// But remember that the `config` and `$` property prefix are designed for tasks that have no schemas.
	// It just won't do anything try to normalize it without schema.
	taskConfig = regulate(taskConfig, ['config']);

	// NOTE: When there is `plugin`,  `task`, `series` or `parallel` property,
	// then all other properties will be treated as properties, not sub-task configs.
	// So user don't have to use `config` keyword or `$` prefix.
	value = _.omit(rawConfig, Object.keys(taskConfig).concat('config'));
	if (!optionalSchema && (taskInfo.plugin || taskInfo.task || taskInfo.series || taskInfo.parallel)) {
		taskConfig = defaults(taskConfig, value);
	} else {
		subTaskConfigs = value;
	}

	// inherit parent's config
	taskConfig = defaults(taskConfig, parentConfig);

	return {
		taskInfo: taskInfo,
		taskConfig: taskConfig,
		subTaskConfigs: subTaskConfigs
	};

	function before(propSchema, values) {
		if (propSchema.type === 'glob') {
			_.defaults(propSchema, glob.SCHEMA);
		} else if (propSchema.type === 'path') {
			_.defaults(propSchema, path.SCHEMA);
		}
	}

	function after(propSchema, resolved) {
		var value, join;

		if (resolved) {
			value = resolved();

			if (propSchema.type === 'glob') {
				join = propSchema.properties.options.properties.join.default || 'src';
				return resolve(resolveSrc(parentConfig, value, join));
			} else if (propSchema.type === 'path') {
				join = propSchema.properties.options.properties.join.default || 'dest';
				return resolve(resolveDest(parentConfig, value, join));
			}
		}

		return resolved;

		function resolve(value) {
			return function () {
				return value;
			};
		}
	}
}
function sort ( taskInfo , rawConfig , parentConfig , optionalSchema ) { var schema , subTaskConfigs , taskConfig , value ; schema = optionalSchema || { } ; from ( schema ) . to ( taskInfo ) . imply ( TASK_SCHEMA_MAPPINGS ) ; schema = defaults ( { } , schema , SCHEMA_DEFAULTS ) ; taskConfig = rawConfig ; // NOTE: If schema provided, try to normalize properties inside 'config' property. if ( optionalSchema ) { taskConfig = regulate ( taskConfig , [ 'config' ] ) ; } taskConfig = normalize ( schema , taskConfig , { before : before , after : after } ) ; taskConfig = renamePatternProperties ( taskConfig ) ; // NOTE: A thought about that `config` should be "normalized". // But remember that the `config` and `$` property prefix are designed for tasks that have no schemas. // It just won't do anything try to normalize it without schema. taskConfig = regulate ( taskConfig , [ 'config' ] ) ; // NOTE: When there is `plugin`,  `task`, `series` or `parallel` property, // then all other properties will be treated as properties, not sub-task configs. // So user don't have to use `config` keyword or `$` prefix. value = _ . omit ( rawConfig , Object . keys ( taskConfig ) . concat ( 'config' ) ) ; if ( ! optionalSchema && ( taskInfo . plugin || taskInfo . task || taskInfo . series || taskInfo . parallel ) ) { taskConfig = defaults ( taskConfig , value ) ; } else { subTaskConfigs = value ; } // inherit parent's config taskConfig = defaults ( taskConfig , parentConfig ) ; return { taskInfo : taskInfo , taskConfig : taskConfig , subTaskConfigs : subTaskConfigs } ; function before ( propSchema , values ) { if ( propSchema . type === 'glob' ) { _ . defaults ( propSchema , glob . SCHEMA ) ; } else if ( propSchema . type === 'path' ) { _ . defaults ( propSchema , path . SCHEMA ) ; } } function after ( propSchema , resolved ) { var value , join ; if ( resolved ) { value = resolved ( ) ; if ( propSchema . type === 'glob' ) { join = propSchema . properties . options . properties . join . default || 'src' ; return resolve ( resolveSrc ( parentConfig , value , join ) ) ; } else if ( propSchema . type === 'path' ) { join = propSchema . properties . options . properties . join . default || 'dest' ; return resolve ( resolveDest ( parentConfig , value , join ) ) ; } } return resolved ; function resolve ( value ) { return function ( ) { return value ; } ; } } }
If both parentConfig and taskConfig specified src property
then try to join paths.
If both parentConfig and taskConfig specified src property then try to join paths .