You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					152 lines
				
				3.7 KiB
			
		
		
			
		
	
	
					152 lines
				
				3.7 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'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;
							 |