152 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			152 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| const path = require('path');
 | |
| const emojisList = require('emojis-list');
 | |
| const getHashDigest = require('./getHashDigest');
 | |
| 
 | |
| const emojiRegex = /[\uD800-\uDFFF]./;
 | |
| const emojiList = emojisList.filter((emoji) => emojiRegex.test(emoji));
 | |
| const emojiCache = {};
 | |
| 
 | |
| function encodeStringToEmoji(content, length) {
 | |
|   if (emojiCache[content]) {
 | |
|     return emojiCache[content];
 | |
|   }
 | |
| 
 | |
|   length = length || 1;
 | |
| 
 | |
|   const emojis = [];
 | |
| 
 | |
|   do {
 | |
|     if (!emojiList.length) {
 | |
|       throw new Error('Ran out of emoji');
 | |
|     }
 | |
| 
 | |
|     const index = Math.floor(Math.random() * emojiList.length);
 | |
| 
 | |
|     emojis.push(emojiList[index]);
 | |
|     emojiList.splice(index, 1);
 | |
|   } while (--length > 0);
 | |
| 
 | |
|   const emojiEncoding = emojis.join('');
 | |
| 
 | |
|   emojiCache[content] = emojiEncoding;
 | |
| 
 | |
|   return emojiEncoding;
 | |
| }
 | |
| 
 | |
| function interpolateName(loaderContext, name, options) {
 | |
|   let filename;
 | |
| 
 | |
|   const hasQuery =
 | |
|     loaderContext.resourceQuery && loaderContext.resourceQuery.length > 1;
 | |
| 
 | |
|   if (typeof name === 'function') {
 | |
|     filename = name(
 | |
|       loaderContext.resourcePath,
 | |
|       hasQuery ? loaderContext.resourceQuery : undefined
 | |
|     );
 | |
|   } else {
 | |
|     filename = name || '[hash].[ext]';
 | |
|   }
 | |
| 
 | |
|   const context = options.context;
 | |
|   const content = options.content;
 | |
|   const regExp = options.regExp;
 | |
| 
 | |
|   let ext = 'bin';
 | |
|   let basename = 'file';
 | |
|   let directory = '';
 | |
|   let folder = '';
 | |
|   let query = '';
 | |
| 
 | |
|   if (loaderContext.resourcePath) {
 | |
|     const parsed = path.parse(loaderContext.resourcePath);
 | |
|     let resourcePath = loaderContext.resourcePath;
 | |
| 
 | |
|     if (parsed.ext) {
 | |
|       ext = parsed.ext.substr(1);
 | |
|     }
 | |
| 
 | |
|     if (parsed.dir) {
 | |
|       basename = parsed.name;
 | |
|       resourcePath = parsed.dir + path.sep;
 | |
|     }
 | |
| 
 | |
|     if (typeof context !== 'undefined') {
 | |
|       directory = path
 | |
|         .relative(context, resourcePath + '_')
 | |
|         .replace(/\\/g, '/')
 | |
|         .replace(/\.\.(\/)?/g, '_$1');
 | |
|       directory = directory.substr(0, directory.length - 1);
 | |
|     } else {
 | |
|       directory = resourcePath.replace(/\\/g, '/').replace(/\.\.(\/)?/g, '_$1');
 | |
|     }
 | |
| 
 | |
|     if (directory.length === 1) {
 | |
|       directory = '';
 | |
|     } else if (directory.length > 1) {
 | |
|       folder = path.basename(directory);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (loaderContext.resourceQuery && loaderContext.resourceQuery.length > 1) {
 | |
|     query = loaderContext.resourceQuery;
 | |
| 
 | |
|     const hashIdx = query.indexOf('#');
 | |
| 
 | |
|     if (hashIdx >= 0) {
 | |
|       query = query.substr(0, hashIdx);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   let url = filename;
 | |
| 
 | |
|   if (content) {
 | |
|     // Match hash template
 | |
|     url = url
 | |
|       // `hash` and `contenthash` are same in `loader-utils` context
 | |
|       // let's keep `hash` for backward compatibility
 | |
|       .replace(
 | |
|         /\[(?:([^[:\]]+):)?(?:hash|contenthash)(?::([a-z]+\d*))?(?::(\d+))?\]/gi,
 | |
|         (all, hashType, digestType, maxLength) =>
 | |
|           getHashDigest(content, hashType, digestType, parseInt(maxLength, 10))
 | |
|       )
 | |
|       .replace(/\[emoji(?::(\d+))?\]/gi, (all, length) =>
 | |
|         encodeStringToEmoji(content, parseInt(length, 10))
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   url = url
 | |
|     .replace(/\[ext\]/gi, () => ext)
 | |
|     .replace(/\[name\]/gi, () => basename)
 | |
|     .replace(/\[path\]/gi, () => directory)
 | |
|     .replace(/\[folder\]/gi, () => folder)
 | |
|     .replace(/\[query\]/gi, () => query);
 | |
| 
 | |
|   if (regExp && loaderContext.resourcePath) {
 | |
|     const match = loaderContext.resourcePath.match(new RegExp(regExp));
 | |
| 
 | |
|     match &&
 | |
|       match.forEach((matched, i) => {
 | |
|         url = url.replace(new RegExp('\\[' + i + '\\]', 'ig'), matched);
 | |
|       });
 | |
|   }
 | |
| 
 | |
|   if (
 | |
|     typeof loaderContext.options === 'object' &&
 | |
|     typeof loaderContext.options.customInterpolateName === 'function'
 | |
|   ) {
 | |
|     url = loaderContext.options.customInterpolateName.call(
 | |
|       loaderContext,
 | |
|       url,
 | |
|       name,
 | |
|       options
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   return url;
 | |
| }
 | |
| 
 | |
| module.exports = interpolateName;
 |