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.
151 lines
3.7 KiB
151 lines
3.7 KiB
'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;
|
|
|