188 lines
6.7 KiB
JavaScript
188 lines
6.7 KiB
JavaScript
(function privateDependencyClosure () {
|
|
/**
|
|
* This primitive class represents Dependency,
|
|
* just to make the work a bit more structured
|
|
* */
|
|
class Dependency {
|
|
constructor (name, contentType) {
|
|
this.name = name;
|
|
this.contentType = contentType;
|
|
}
|
|
|
|
/**
|
|
* This function goes through an array of strings and number to make sense of it
|
|
*
|
|
* @param {Array} deps - an array of strings and numbers
|
|
*
|
|
* @returns Array<Dependency>
|
|
* */
|
|
static refineDependencies (deps) {
|
|
const result = [];
|
|
const collection = Object.create(null);
|
|
for (let i = 0; i < deps.length; ++i) {
|
|
let element = deps[i];
|
|
const elementType = typeof element
|
|
if (!collection[element] && elementType === "string") {
|
|
result.push(new Dependency(element));
|
|
collection[element] = true;
|
|
} else if (result.length > 0 && elementType === "number" && ReverseType[element] !== undefined) {
|
|
let prevResult = result[result.length - 1];
|
|
if (deps[i - 1] === prevResult.name)
|
|
prevResult.contentType = element;
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
/**
|
|
* Checks one type against another and writes a warning if they don't match
|
|
*
|
|
* @param {Type} original
|
|
* @param {Type} current
|
|
* @param {String} path
|
|
* */
|
|
static checkContentType (original, current, path) {
|
|
if (original !== current) {
|
|
const originalType = ReverseType[original];
|
|
const currentType = ReverseType[current];
|
|
console.warn("Mimicry error: file " + path +
|
|
" was originally requested as " + originalType +
|
|
" but next time it was requested as " + currentType +
|
|
" ignoring second request type and treating file as " + originalType
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Refines path turning all meta information into a path to query
|
|
*
|
|
* @typedef Mimicry.Type Type
|
|
*
|
|
* @param {String} path - a source path
|
|
* @param {Type} type - type of the content
|
|
* @param {String} baseUrl - path to all project files
|
|
* @param {Map<Type, String>} types - collection of paths to specific content types
|
|
* @param {Map<String, String>} libs - collection of paths to libraries
|
|
*
|
|
* @returns {String}
|
|
* */
|
|
static refinePath (path, type, baseUrl, types, libs) {
|
|
const suffix = suffixes[type];
|
|
const typePath = types.get(type) || "";
|
|
if (!path.endsWith(suffix))
|
|
path += suffix;
|
|
|
|
switch (type) {
|
|
case Type.js:
|
|
if (path[0] === "@") {
|
|
const hops = path.split("/");
|
|
const libName = hops[0].slice(1);
|
|
let libPath = libs.get(libName);
|
|
if (libPath === undefined)
|
|
libPath = libName;
|
|
|
|
path = baseUrl + libPath + path.slice(libName.length + 1);
|
|
} else {
|
|
path = baseUrl + typePath + path;
|
|
}
|
|
break;
|
|
default:
|
|
path = baseUrl + typePath + path;
|
|
break;
|
|
}
|
|
|
|
return path;
|
|
}
|
|
|
|
/**
|
|
* @param {Array<String>} dependencies - list of module names that this module depends on
|
|
* @param {Function} [callback] - module body that will be executed as soon all dependencies are resolved
|
|
* */
|
|
static refineModuleArguments (dependencies, callback) {
|
|
let deps, body;
|
|
if (dependencies instanceof Function) {
|
|
body = dependencies;
|
|
deps = [];
|
|
} else {
|
|
deps = dependencies;
|
|
body = callback;
|
|
}
|
|
|
|
deps = this.refineDependencies(deps);
|
|
|
|
return {deps, body};
|
|
}
|
|
|
|
/**
|
|
* @param {String} href - script DOM element that launched this function
|
|
* @param {String} baseUrl - path to all project files
|
|
* @param {Map<Type, String>} types - collection of paths to specific content types
|
|
* @param {Map<String, String>} libs - collection of paths to libraries
|
|
* */
|
|
static nameFromHref (href, baseUrl, types, libs) {
|
|
const suffix = suffixes[Type.js];
|
|
const typePath = types.get(Type.js) || "";
|
|
|
|
if (href.endsWith(suffix))
|
|
href = href.slice(0, -suffix.length);
|
|
|
|
if (baseUrl.length) {
|
|
const baseIndex = href.indexOf(baseUrl);
|
|
if (baseIndex !== 0)
|
|
console.warn("Module path " + href +
|
|
" doesn't start with baseUrl " + baseUrl +
|
|
", this is probably an error");
|
|
else
|
|
href = href.slice(baseUrl.length + 1);
|
|
}
|
|
|
|
let foundAmongLibs = false;
|
|
for (const [libName, libPath] of libs) {
|
|
const index = href.indexOf(libPath);
|
|
if (index === 0) {
|
|
href = "@" + libName + href.slice(libPath.length);
|
|
foundAmongLibs = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!foundAmongLibs && typePath.length) {
|
|
const typeIndex = href.indexOf(typePath);
|
|
if (typeIndex !== 0)
|
|
console.warn("Module path " + href +
|
|
" doesn't start with a proper type path " + typePath +
|
|
", this is probably an error");
|
|
else
|
|
href = href.slice(typePath.length + 1);
|
|
}
|
|
|
|
return href;
|
|
}
|
|
|
|
static get Type () {return Type;}
|
|
static getTypeTitle (/*Type*/type) {return ReverseType[type];}
|
|
}
|
|
|
|
const Type = {
|
|
none: 0, //just to prevent implicit situations, DON'T USE IT!
|
|
js: 1,
|
|
css: 2,
|
|
json: 3,
|
|
binary: 4,
|
|
text: 5
|
|
};
|
|
|
|
const suffixes = ["", ".js", ".css", ".json", "", ""];
|
|
const ReverseType = ["None", "JavaScript", "CSS", "JSON", "Binary", "Text"];
|
|
|
|
Object.freeze(Type);
|
|
Object.freeze(suffixes);
|
|
Object.freeze(ReverseType);
|
|
|
|
if (typeof module === 'object' && module.exports)
|
|
module.exports = Dependency;
|
|
else
|
|
window.__MimicryDependency__ = Dependency;
|
|
})();
|
|
|
|
|