'use strict'; var helpers = require( 'postcss-helpers' ); var util = require( 'util' ); /** * Checks validity of config object. * @private * @param {Object} config Configuration object */ var validateConfig = function( config ) { if ( !config || !config.rules ) { throw new Error( 'You must configure at least one replace rule.' ); } if ( !util.isArray( config.rules ) && typeof config.rules !== 'function' ) { throw new Error( 'Rules must be an Array or Function.' ); } if ( util.isArray( config.rules ) ) { config.rules.forEach( function ( rule ) { if ( !rule.from && !rule.to ) { throw new Error( 'Rules must be in { from: "from", to: "to" } format.' ); } else if ( typeof rule.from !== 'string' && !util.isRegExp( rule.from ) ) { throw new Error( 'Rule.from must be a String or RegExp.' ); } else if ( [ 'string', 'function' ].indexOf( typeof rule.to ) === -1 ) { throw new Error( 'Rule.to must be a String or Function.' ); } } ); } if ( config.properties && !Array.isArray( config.properties ) && !( typeof config.properties === 'boolean' ) ) { throw new Error( 'Properties must be an Array of Strings or Boolean.' ); } if ( Array.isArray( config.properties ) ) { config.properties.forEach( function( prop ) { if ( typeof prop !== 'string' ) { throw new Error( 'Items in "properties" array must be Strings.' ); } } ); } }; /** * Returns callback function for URI replacement based on config params. * @private * @param {Array} rules Array of objects with "from" and "to" keys to use * as arguments to String.replace. * @returns {Function} Callback function. */ var useRulesCallback = function( rules ) { rules = rules; return function( uri ) { var modified = false; var original = uri.href(); rules.forEach( function( rule ) { if ( modified ) { return; } var tmp = original.replace( rule.from, rule.to ); if ( tmp !== original ) { modified = true; uri.href( tmp ); } } ); }; }; /** * Plugin body. * @param {Boolean} config.imports If set to true, will also replace @import values. * @param {Array|Boolean} config.properties List of css properties to update or false. * @param {Array|Function} config.rules Array of replace params or * callback function. * @returns {Function} PostCSS plugin. */ var urlrewrite = function( config ) { validateConfig( config ); // Choosing which callback to use: One received from user or autogenerated // from params. var callback = ( Array.isArray( config.rules ) ) ? useRulesCallback( config.rules ) : config.rules; // Function to update @import URIs var updateImport = function( atRule ) { if( atRule.name !== 'import' ) { return; } var helper = helpers.createImportHelper( atRule.params ); callback( helper.URI ); atRule.params = helper.getModifiedRule(); }; // Function to update declarations URIs var updateDecl = function( decl ) { if ( config.properties === false ) { return; } if ( Array.isArray( config.properties ) && config.properties.indexOf( decl.prop ) === -1 ) { return; } if ( !decl.value.match( helpers.regexp.URLS ) ) { return; } var helper = helpers.createUrlsHelper( decl.value ); helper.URIS.forEach( callback ); decl.value = helper.getModifiedRule(); }; return function( style ) { if ( config.imports ) { style.walkAtRules( updateImport ); } if ( config.properties !== false ) { style.walkDecls( updateDecl ); } }; }; module.exports = urlrewrite;