Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@jsenv/import-map

Package Overview
Dependencies
Maintainers
2
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@jsenv/import-map - npm Package Compare versions

Comparing version 5.5.0 to 6.2.0

src/hasScheme.js

1161

dist/commonjs/main.js

@@ -5,413 +5,374 @@ 'use strict';

var nativeTypeOf = function nativeTypeOf(obj) {
return typeof obj;
};
var customTypeOf = function customTypeOf(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? nativeTypeOf : customTypeOf;
var assertImportMap = function assertImportMap(value) {
const assertImportMap = value => {
if (value === null) {
throw new TypeError("an importMap must be an object, got null");
throw new TypeError(`an importMap must be an object, got null`);
}
var type = _typeof(value);
const type = typeof value;
if (type !== "object") {
throw new TypeError("an importMap must be an object, received ".concat(value));
throw new TypeError(`an importMap must be an object, received ${value}`);
}
if (Array.isArray(value)) {
throw new TypeError("an importMap must be an object, received array ".concat(value));
throw new TypeError(`an importMap must be an object, received array ${value}`);
}
};
// "https://domain.com/folder/file.js"
// "file:///folder/file.js"
// "chrome://folder/file.js"
var isAbsoluteSpecifier = function isAbsoluteSpecifier(specifier) {
if (isWindowsDriveSpecifier(specifier)) {
// window drive letter could are not protocol yep
// something like `C:/folder/file.js`
// will be considered as a bare import
return false;
}
const hasScheme = string => {
return /^[a-zA-Z]{2,}:/.test(string);
};
return /^[a-zA-Z]+:/.test(specifier);
}; // https://url.spec.whatwg.org/#example-start-with-a-widows-drive-letter
var isWindowsDriveSpecifier = function isWindowsDriveSpecifier(specifier) {
var firstChar = specifier[0];
if (!/[a-zA-Z]/.test(firstChar)) return false;
var secondChar = specifier[1];
if (secondChar !== ":") return false;
var thirdChar = specifier[2];
return thirdChar === "/";
const hrefToScheme = href => {
const colonIndex = href.indexOf(":");
if (colonIndex === -1) return "";
return href.slice(0, colonIndex);
};
var resolveAbsoluteSpecifier = function resolveAbsoluteSpecifier(specifier) {
return specifier;
const hrefToPathname = href => {
return ressourceToPathname(hrefToRessource(href));
};
var assertUrlLike = function assertUrlLike(value) {
var name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "specifier";
const hrefToRessource = href => {
const scheme = hrefToScheme(href);
if (typeof value !== "string") {
throw new TypeError("".concat(name, " must be a string, got ").concat(value));
if (scheme === "file") {
return href.slice("file://".length);
}
if (!isAbsoluteSpecifier(value)) {
throw new Error("".concat(name, " must be a url and no scheme found, got ").concat(value));
if (scheme === "https" || scheme === "http") {
// remove origin
const afterProtocol = href.slice(scheme.length + "://".length);
const pathnameSlashIndex = afterProtocol.indexOf("/", "://".length);
return afterProtocol.slice(pathnameSlashIndex);
}
return href.slice(scheme.length + 1);
};
var applyImportMap = function applyImportMap(_ref) {
var importMap = _ref.importMap,
href = _ref.href,
importerHref = _ref.importerHref;
assertImportMap(importMap);
assertUrlLike(href, "href");
const ressourceToPathname = ressource => {
const searchSeparatorIndex = ressource.indexOf("?");
return searchSeparatorIndex === -1 ? ressource : ressource.slice(0, searchSeparatorIndex);
};
if (importerHref) {
assertUrlLike(importerHref, "importerHref");
}
const hrefToOrigin = href => {
const scheme = hrefToScheme(href);
var scopes = importMap.scopes;
if (scopes && importerHref) {
var scopeKeyMatching = Object.keys(scopes).find(function (scopeKey) {
return scopeKey === importerHref || specifierIsPrefixOf(scopeKey, importerHref);
});
if (scopeKeyMatching) {
var scopeValue = scopes[scopeKeyMatching];
var remappingFromScopeImports = applyImports(href, scopeValue);
if (remappingFromScopeImports !== null) {
return remappingFromScopeImports;
}
}
if (scheme === "file") {
return "file://";
}
var imports = importMap.imports;
if (imports) {
var remappingFromImports = applyImports(href, imports);
if (remappingFromImports !== null) {
return remappingFromImports;
}
if (scheme === "http" || scheme === "https") {
const secondProtocolSlashIndex = scheme.length + "://".length;
const pathnameSlashIndex = href.indexOf("/", secondProtocolSlashIndex);
if (pathnameSlashIndex === -1) return href;
return href.slice(0, pathnameSlashIndex);
}
return href;
return href.slice(0, scheme.length + 1);
};
var applyImports = function applyImports(href, imports) {
var importKeyArray = Object.keys(imports);
var i = 0;
const pathnameToDirname = pathname => {
const slashLastIndex = pathname.lastIndexOf("/");
if (slashLastIndex === -1) return "";
return pathname.slice(0, slashLastIndex);
};
while (i < importKeyArray.length) {
var importKey = importKeyArray[i];
i++;
if (importKey === href) {
var importValue = imports[importKey];
return importValue;
// could be useful: https://url.spec.whatwg.org/#url-miscellaneous
const resolveUrl = (specifier, baseUrl) => {
if (baseUrl) {
if (typeof baseUrl !== "string") {
throw new TypeError(writeBaseUrlMustBeAString({
baseUrl,
specifier
}));
}
if (specifierIsPrefixOf(importKey, href)) {
var _importValue = imports[importKey];
var afterImportKey = href.slice(importKey.length);
return _importValue + afterImportKey;
if (!hasScheme(baseUrl)) {
throw new Error(writeBaseUrlMustBeAbsolute({
baseUrl,
specifier
}));
}
}
return null;
};
var specifierIsPrefixOf = function specifierIsPrefixOf(specifierHref, href) {
return specifierHref[specifierHref.length - 1] === "/" && href.startsWith(specifierHref);
};
var defineProperty = (function (obj, key, value) {
// Shortcircuit the slow defineProperty path when possible.
// We are trying to avoid issues where setters defined on the
// prototype cause side effects under the fast path of simple
// assignment. By checking for existence of the property with
// the in operator, we can optimize most of this overhead away.
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
if (hasScheme(specifier)) {
return specifier;
}
return obj;
});
if (!baseUrl) {
throw new Error(writeBaseUrlRequired({
baseUrl,
specifier
}));
} // scheme relative
function _objectSpread (target) {
for (var i = 1; i < arguments.length; i++) {
// eslint-disable-next-line prefer-rest-params
var source = arguments[i] === null ? {} : arguments[i];
if (i % 2) {
// eslint-disable-next-line no-loop-func
ownKeys(source, true).forEach(function (key) {
defineProperty(target, key, source[key]);
});
} else if (Object.getOwnPropertyDescriptors) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
} else {
// eslint-disable-next-line no-loop-func
ownKeys(source).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
}
if (specifier.slice(0, 2) === "//") {
return `${hrefToScheme(baseUrl)}:${specifier}`;
} // origin relative
return target;
} // This function is different to "Reflect.ownKeys". The enumerableOnly
// filters on symbol properties only. Returned string properties are always
// enumerable. It is good to use in objectSpread.
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
if (enumerableOnly) symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
}); // eslint-disable-next-line prefer-spread
keys.push.apply(keys, symbols);
if (specifier[0] === "/") {
return `${hrefToOrigin(baseUrl)}${specifier}`;
}
return keys;
}
const baseOrigin = hrefToOrigin(baseUrl);
const basePathname = hrefToPathname(baseUrl); // pathname relative inside
var composeTwoImportMaps = function composeTwoImportMaps(leftImportMap, rightImportMap) {
assertImportMap(leftImportMap);
assertImportMap(rightImportMap);
return {
imports: composeTwoImports(leftImportMap.imports, rightImportMap.imports),
scopes: composeTwoScopes(leftImportMap.scopes, rightImportMap.scopes)
};
};
if (specifier.slice(0, 2) === "./") {
const baseDirname = pathnameToDirname(basePathname);
return `${baseOrigin}${baseDirname}/${specifier.slice(2)}`;
} // pathname relative outside
var composeTwoImports = function composeTwoImports() {
var leftImports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var rightImports = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
return _objectSpread({}, leftImports, {}, rightImports);
};
var composeTwoScopes = function composeTwoScopes() {
var leftScopes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var rightScopes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
if (specifier.slice(0, 3) === "../") {
let unresolvedPathname = specifier;
const importerFolders = basePathname.split("/");
importerFolders.pop();
var scopes = _objectSpread({}, leftScopes);
while (unresolvedPathname.slice(0, 3) === "../") {
// when there is no folder left to resolved
// we just ignore '../'
if (importerFolders.length) {
importerFolders.pop();
}
Object.keys(rightScopes).forEach(function (scopeKey) {
if (scopes.hasOwnProperty(scopeKey)) {
scopes[scopeKey] = _objectSpread({}, scopes[scopeKey], {}, rightScopes[scopeKey]);
} else {
scopes[scopeKey] = _objectSpread({}, rightScopes[scopeKey]);
unresolvedPathname = unresolvedPathname.slice(3);
}
});
return scopes;
};
var hrefToScheme = function hrefToScheme(href) {
var colonIndex = href.indexOf(":");
if (colonIndex === -1) return "";
return href.slice(0, colonIndex);
};
const resolvedPathname = `${importerFolders.join("/")}/${unresolvedPathname}`;
return `${baseOrigin}${resolvedPathname}`;
} // bare
var hrefToOrigin = function hrefToOrigin(href) {
var scheme = hrefToScheme(href);
if (scheme === "file") {
return "file://";
if (basePathname === "") {
return `${baseOrigin}/${specifier}`;
}
if (scheme === "http" || scheme === "https") {
var secondProtocolSlashIndex = scheme.length + "://".length;
var pathnameSlashIndex = href.indexOf("/", secondProtocolSlashIndex);
if (pathnameSlashIndex === -1) return href;
return href.slice(0, pathnameSlashIndex);
if (basePathname[basePathname.length] === "/") {
return `${baseOrigin}${basePathname}${specifier}`;
}
return href.slice(0, scheme.length + 1);
return `${baseOrigin}${pathnameToDirname(basePathname)}/${specifier}`;
};
var hrefToPathname = function hrefToPathname(href) {
return ressourceToPathname(hrefToRessource(href));
const writeBaseUrlMustBeAString = ({
baseUrl,
specifier
}) => `baseUrl must be a string.
--- base url ---
${baseUrl}
--- specifier ---
${specifier}`;
const writeBaseUrlMustBeAbsolute = ({
baseUrl,
specifier
}) => `baseUrl must be absolute.
--- base url ---
${baseUrl}
--- specifier ---
${specifier}`;
const writeBaseUrlRequired = ({
baseUrl,
specifier
}) => `baseUrl required to resolve relative specifier.
--- base url ---
${baseUrl}
--- specifier ---
${specifier}`;
const tryUrlResolution = (string, url) => {
const result = resolveUrl(string, url);
return hasScheme(result) ? result : null;
};
var hrefToRessource = function hrefToRessource(href) {
var scheme = hrefToScheme(href);
if (scheme === "file") {
return href.slice("file://".length);
const resolveSpecifier = (specifier, importer) => {
if (specifier[0] === "/" || specifier.startsWith("./") || specifier.startsWith("../")) {
return resolveUrl(specifier, importer);
}
if (scheme === "https" || scheme === "http") {
// remove origin
var afterProtocol = href.slice(scheme.length + "://".length);
var pathnameSlashIndex = afterProtocol.indexOf("/", "://".length);
return afterProtocol.slice(pathnameSlashIndex);
if (hasScheme(specifier)) {
return specifier;
}
return href.slice(scheme.length + 1);
return null;
};
var ressourceToPathname = function ressourceToPathname(ressource) {
var searchSeparatorIndex = ressource.indexOf("?");
return searchSeparatorIndex === -1 ? ressource : ressource.slice(0, searchSeparatorIndex);
};
const applyImportMap = ({
importMap,
specifier,
importer
}) => {
assertImportMap(importMap);
var pathnameToDirname = function pathnameToDirname(pathname) {
var slashLastIndex = pathname.lastIndexOf("/");
if (slashLastIndex === -1) return "";
return pathname.slice(0, slashLastIndex);
};
if (typeof specifier !== "string") {
throw new TypeError(writeSpecifierMustBeAString({
specifier,
importer
}));
}
var pathnameToExtension = function pathnameToExtension(pathname) {
var slashLastIndex = pathname.lastIndexOf("/");
if (importer) {
if (typeof importer !== "string") {
throw new TypeError(writeImporterMustBeAString({
importer,
specifier
}));
}
if (slashLastIndex !== -1) {
pathname = pathname.slice(slashLastIndex + 1);
if (!hasScheme(importer)) {
throw new Error(writeImporterMustBeAbsolute({
importer,
specifier
}));
}
}
var dotLastIndex = pathname.lastIndexOf(".");
if (dotLastIndex === -1) return ""; // if (dotLastIndex === pathname.length - 1) return ""
const specifierUrl = resolveSpecifier(specifier, importer);
const specifierNormalized = specifierUrl || specifier;
const {
scopes
} = importMap;
return pathname.slice(dotLastIndex);
};
if (scopes && importer) {
const scopeKeyMatching = Object.keys(scopes).find(scopeKey => {
return scopeKey === importer || specifierIsPrefixOf(scopeKey, importer);
});
var pathnameToRelativePath = function pathnameToRelativePath(pathname, otherPathname) {
return pathname.slice(otherPathname.length);
};
if (scopeKeyMatching) {
const scopeValue = scopes[scopeKeyMatching];
const remappingFromScopeImports = applyImports(specifierNormalized, scopeValue);
var isSchemeRelativeSpecifier = function isSchemeRelativeSpecifier(specifier) {
return specifier.slice(0, 2) === "//";
};
var resolveSchemeRelativeSpecifier = function resolveSchemeRelativeSpecifier(specifier, importer) {
return "".concat(hrefToScheme(importer), ":").concat(specifier);
};
if (remappingFromScopeImports !== null) {
return remappingFromScopeImports;
}
}
}
var isOriginRelativeSpecifier = function isOriginRelativeSpecifier(specifier) {
var firstChar = specifier[0];
if (firstChar !== "/") return false;
var secondChar = specifier[1];
if (secondChar === "/") return false;
return true;
};
var resolveOriginRelativeSpecifier = function resolveOriginRelativeSpecifier(specifier, importer) {
var importerOrigin = hrefToOrigin(importer);
return "".concat(importerOrigin, "/").concat(specifier.slice(1));
};
const {
imports
} = importMap;
// https://github.com/systemjs/systemjs/blob/master/src/common.js
// "../folder/file.js"
if (imports) {
const remappingFromImports = applyImports(specifierNormalized, imports);
var isPathnameRelativeSpecifier = function isPathnameRelativeSpecifier(specifier) {
if (specifier.slice(0, 2) === "./") return true;
if (specifier.slice(0, 3) === "../") return true;
return false;
};
var resolvePathnameRelativeSpecifier = function resolvePathnameRelativeSpecifier(specifier, importer) {
var importerPathname = hrefToPathname(importer); // ./foo.js on /folder/file.js -> /folder/foo.js
// ./foo/bar.js on /folder/file.js -> /folder/foo/bar.js
// ./foo.js on /folder/subfolder/file.js -> /folder/subfolder/foo.js
if (remappingFromImports !== null) {
return remappingFromImports;
}
}
if (specifier.slice(0, 2) === "./") {
var _importerOrigin = hrefToOrigin(importer);
if (specifierUrl) {
return specifierUrl;
}
var importerDirname = pathnameToDirname(importerPathname);
return "".concat(_importerOrigin).concat(importerDirname, "/").concat(specifier.slice(2));
} // ../foo/bar.js on /folder/file.js -> /foo/bar.js
// ../foo/bar.js on /folder/subfolder/file.js -> /folder/foo/bar.js
// ../../foo/bar.js on /folder/file.js -> /foo/bar.js
// ../bar.js on / -> /bar.js
throw new Error(writeBareSpecifierMustBeRemapped({
specifier,
importer
}));
};
const applyImports = (specifier, imports) => {
const importKeyArray = Object.keys(imports);
let i = 0;
var unresolvedPathname = specifier;
var importerFolders = importerPathname.split("/");
importerFolders.pop(); // remove file, it is not a folder
while (i < importKeyArray.length) {
const importKey = importKeyArray[i];
i++;
while (unresolvedPathname.slice(0, 3) === "../") {
// when there is no folder left to resolved
// we just ignore '../'
if (importerFolders.length) {
importerFolders.pop();
if (importKey === specifier) {
const importValue = imports[importKey];
return importValue;
}
unresolvedPathname = unresolvedPathname.slice(3);
if (specifierIsPrefixOf(importKey, specifier)) {
const importValue = imports[importKey];
const afterImportKey = specifier.slice(importKey.length);
return tryUrlResolution(afterImportKey, importValue);
}
}
var importerOrigin = hrefToOrigin(importer);
var resolvedPathname = "".concat(importerFolders.join("/"), "/").concat(unresolvedPathname);
return "".concat(importerOrigin).concat(resolvedPathname);
return null;
};
var isBareSpecifier = function isBareSpecifier(specifier) {
if (isAbsoluteSpecifier(specifier)) return false;
if (isSchemeRelativeSpecifier(specifier)) return false;
if (isOriginRelativeSpecifier(specifier)) return false;
if (isPathnameRelativeSpecifier(specifier)) return false;
return true;
const specifierIsPrefixOf = (specifierHref, href) => {
return specifierHref[specifierHref.length - 1] === "/" && href.startsWith(specifierHref);
};
var resolveBareSpecifier = function resolveBareSpecifier(specifier, importer) {
var importerOrigin = hrefToOrigin(importer);
return "".concat(importerOrigin, "/").concat(specifier);
};
// could be useful: https://url.spec.whatwg.org/#url-miscellaneous
var resolveSpecifier = function resolveSpecifier(specifier, importer) {
if (isAbsoluteSpecifier(specifier)) {
return resolveAbsoluteSpecifier(specifier);
}
const writeSpecifierMustBeAString = ({
specifier,
importer
}) => `specifier must be a string.
--- specifier ---
${specifier}
--- importer ---
${importer}`;
if (!importer) {
throw new Error(createMissingImporterMessage(specifier, importer));
}
const writeImporterMustBeAString = ({
importer,
specifier
}) => `importer must be a string.
--- importer ---
${importer}
--- specifier ---
${specifier}`;
if (!isAbsoluteSpecifier(importer)) {
throw new Error(createAbsoluteImporterRequiredMessage(importer));
}
const writeImporterMustBeAbsolute = ({
importer,
specifier
}) => `importer must be an absolute url.
--- importer ---
${importer}
--- specifier ---
${specifier}`;
if (isSchemeRelativeSpecifier(specifier)) {
return resolveSchemeRelativeSpecifier(specifier, importer);
}
const writeBareSpecifierMustBeRemapped = ({
specifier,
importer
}) => `Unmapped bare specifier.
--- specifier ---
${specifier}
--- importer ---
${importer}`;
if (isOriginRelativeSpecifier(specifier)) {
return resolveOriginRelativeSpecifier(specifier, importer);
}
if (isPathnameRelativeSpecifier(specifier)) {
return resolvePathnameRelativeSpecifier(specifier, importer);
}
return resolveBareSpecifier(specifier, importer);
// https://github.com/systemjs/systemjs/blob/89391f92dfeac33919b0223bbf834a1f4eea5750/src/common.js#L136
const composeTwoImportMaps = (leftImportMap, rightImportMap) => {
assertImportMap(leftImportMap);
assertImportMap(rightImportMap);
return {
imports: composeTwoImports(leftImportMap.imports, rightImportMap.imports),
scopes: composeTwoScopes(leftImportMap.scopes, rightImportMap.scopes)
};
};
var createMissingImporterMessage = function createMissingImporterMessage(specifier, importer) {
return "missing importer to resolve relative specifier.\n--- specifier ---\n".concat(specifier, "\n--- importer ---\n").concat(importer);
const composeTwoImports = (leftImports = {}, rightImports = {}) => {
return { ...leftImports,
...rightImports
};
};
var createAbsoluteImporterRequiredMessage = function createAbsoluteImporterRequiredMessage(importer) {
return "importer must be absolute.\n--- importer ---\n".concat(importer);
const composeTwoScopes = (leftScopes = {}, rightScopes = {}) => {
const scopes = { ...leftScopes
};
Object.keys(rightScopes).forEach(scopeKey => {
if (scopes.hasOwnProperty(scopeKey)) {
scopes[scopeKey] = { ...scopes[scopeKey],
...rightScopes[scopeKey]
};
} else {
scopes[scopeKey] = { ...rightScopes[scopeKey]
};
}
});
return scopes;
};
var sortImportMap = function sortImportMap(importMap) {
const sortImportMap = importMap => {
assertImportMap(importMap);
var imports = importMap.imports,
scopes = importMap.scopes;
const {
imports,
scopes
} = importMap;
return {

@@ -422,5 +383,5 @@ imports: imports ? sortImports(imports) : undefined,

};
var sortImports = function sortImports(imports) {
var importsSorted = {};
Object.keys(imports).sort(compareLengthOrLocaleCompare).forEach(function (name) {
const sortImports = imports => {
const importsSorted = {};
Object.keys(imports).sort(compareLengthOrLocaleCompare).forEach(name => {
importsSorted[name] = imports[name];

@@ -430,5 +391,5 @@ });

};
var sortScopes = function sortScopes(scopes) {
var scopesSorted = {};
Object.keys(scopes).sort(compareLengthOrLocaleCompare).forEach(function (scopeName) {
const sortScopes = scopes => {
const scopesSorted = {};
Object.keys(scopes).sort(compareLengthOrLocaleCompare).forEach(scopeName => {
scopesSorted[scopeName] = sortImports(scopes[scopeName]);

@@ -439,28 +400,60 @@ });

var compareLengthOrLocaleCompare = function compareLengthOrLocaleCompare(a, b) {
const compareLengthOrLocaleCompare = (a, b) => {
return b.length - a.length || a.localeCompare(b);
};
var normalizeImportMap = function normalizeImportMap(importMap, href) {
const normalizeImportMap = (importMap, baseUrl) => {
assertImportMap(importMap);
if (typeof href !== "string") {
throw new TypeError("href must be a string, got ".concat(href));
if (typeof baseUrl !== "string") {
throw new TypeError(formulateBaseUrlMustBeAString({
baseUrl
}));
}
var imports = importMap.imports,
scopes = importMap.scopes;
const {
imports,
scopes
} = importMap;
return {
imports: imports ? normalizeImports(imports, href) : undefined,
scopes: scopes ? normalizeScopes(scopes, href) : undefined
imports: imports ? normalizeImports(imports, baseUrl) : undefined,
scopes: scopes ? normalizeScopes(scopes, baseUrl) : undefined
};
};
var normalizeImports = function normalizeImports(imports, href) {
var importsNormalized = {};
Object.keys(imports).forEach(function (importKey) {
var importValue = imports[importKey];
var importKeyNormalized = resolveSpecifier(importKey, href);
var importValueNormalized = resolveSpecifier(importValue, href);
importsNormalized[importKeyNormalized] = importValueNormalized;
const normalizeImports = (imports, baseUrl) => {
const importsNormalized = {};
Object.keys(imports).forEach(specifier => {
const address = imports[specifier];
if (typeof address !== "string") {
console.warn(formulateAddressMustBeAString({
address,
specifier
}));
return;
}
const specifierResolved = resolveSpecifier(specifier, baseUrl) || specifier;
const addressUrl = tryUrlResolution(address, baseUrl);
if (addressUrl === null) {
console.warn(formulateAdressResolutionFailed({
address,
baseUrl,
specifier
}));
return;
}
if (specifier.endsWith("/") && !addressUrl.endsWith("/")) {
console.warn(formulateAddressUrlRequiresTrailingSlash({
addressUrl,
address,
specifier
}));
return;
}
importsNormalized[specifierResolved] = addressUrl;
});

@@ -470,9 +463,18 @@ return sortImports(importsNormalized);

var normalizeScopes = function normalizeScopes(scopes, href) {
var scopesNormalized = {};
Object.keys(scopes).forEach(function (scopeKey) {
var scopeValue = scopes[scopeKey];
var scopeKeyNormalized = resolveSpecifier(scopeKey, href);
var scopeValueNormalized = normalizeImports(scopeValue, href);
scopesNormalized[scopeKeyNormalized] = scopeValueNormalized;
const normalizeScopes = (scopes, baseUrl) => {
const scopesNormalized = {};
Object.keys(scopes).forEach(scope => {
const scopeValue = scopes[scope];
const scopeUrl = tryUrlResolution(scope, baseUrl);
if (scopeUrl === null) {
console.warn(formulateScopeResolutionFailed({
scope,
baseUrl
}));
return;
}
const scopeValueNormalized = normalizeImports(scopeValue, baseUrl);
scopesNormalized[scopeUrl] = scopeValueNormalized;
});

@@ -482,48 +484,117 @@ return sortScopes(scopesNormalized);

var normalizeImportMapForProject = function normalizeImportMapForProject(importMap) {
var httpResolutionOrigin = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "http://fake_origin_unlikely_to_collide.ext";
const formulateBaseUrlMustBeAString = ({
baseUrl
}) => `baseUrl must be a string.
--- base url ---
${baseUrl}`;
const formulateAddressMustBeAString = ({
specifier,
address
}) => `Address must be a string.
--- address ---
${address}
--- specifier ---
${specifier}`;
const formulateAdressResolutionFailed = ({
address,
baseUrl,
specifier
}) => `Address url resolution failed.
--- address ---
${address}
--- base url ---
${baseUrl}
--- specifier ---
${specifier}`;
const formulateAddressUrlRequiresTrailingSlash = ({
addressURL,
address,
specifier
}) => `Address must end with /.
--- address url ---
${addressURL}
--- address ---
${address}
--- specifier ---
${specifier}`;
const formulateScopeResolutionFailed = ({
scope,
baseUrl
}) => `Scope url resolution failed.
--- scope ---
${scope}
--- base url ---
${baseUrl}`;
const normalizeImportMapForProject = (importMap, httpResolutionOrigin = "http://fake_origin_unlikely_to_collide.ext") => {
return normalizeImportMap(importMap, httpResolutionOrigin);
};
const pathnameToExtension = pathname => {
const slashLastIndex = pathname.lastIndexOf("/");
if (slashLastIndex !== -1) {
pathname = pathname.slice(slashLastIndex + 1);
}
const dotLastIndex = pathname.lastIndexOf(".");
if (dotLastIndex === -1) return ""; // if (dotLastIndex === pathname.length - 1) return ""
return pathname.slice(dotLastIndex);
};
// directly target the files because this code
var resolveImport = function resolveImport(_ref) {
var specifier = _ref.specifier,
importer = _ref.importer,
importMap = _ref.importMap,
_ref$defaultExtension = _ref.defaultExtension,
defaultExtension = _ref$defaultExtension === void 0 ? true : _ref$defaultExtension;
var specifierResolved = resolveSpecifier(specifier, importer);
var specifierRemapped = importMap ? applyImportMap({
importMap: importMap,
href: specifierResolved,
importerHref: importer
}) : specifierResolved;
const resolveImport = ({
specifier,
importer,
importMap,
defaultExtension = true
}) => {
return applyDefaultExtension({
url: importMap ? applyImportMap({
importMap,
specifier,
importer
}) : resolveUrl(specifier, importer),
importer,
defaultExtension
});
};
const applyDefaultExtension = ({
url,
importer,
defaultExtension
}) => {
if (typeof defaultExtension === "string") {
var extension = pathnameToExtension(specifierRemapped);
const extension = pathnameToExtension(url);
if (extension === "") {
return "".concat(specifierRemapped).concat(defaultExtension);
return `${url}${defaultExtension}`;
}
return url;
}
if (defaultExtension === true) {
var _extension = pathnameToExtension(specifierRemapped);
const extension = pathnameToExtension(url);
if (_extension === "") {
if (importer) {
var importerPathname = hrefToPathname(importer);
var importerExtension = pathnameToExtension(importerPathname);
return "".concat(specifierRemapped).concat(importerExtension);
}
if (extension === "" && importer) {
const importerPathname = hrefToPathname(importer);
const importerExtension = pathnameToExtension(importerPathname);
return `${url}${importerExtension}`;
}
}
return specifierRemapped;
return url;
};
var startsWithWindowsDriveLetter = function startsWithWindowsDriveLetter(string) {
var firstChar = string[0];
const startsWithWindowsDriveLetter = string => {
const firstChar = string[0];
if (!/[a-zA-Z]/.test(firstChar)) return false;
var secondChar = string[1];
const secondChar = string[1];
if (secondChar !== ":") return false;

@@ -533,9 +604,7 @@ return true;

var replaceSlashesWithBackSlashes = function replaceSlashesWithBackSlashes(string) {
return string.replace(/\//g, "\\");
};
const replaceSlashesWithBackSlashes = string => string.replace(/\//g, "\\");
var pathnameToOperatingSystemPath = function pathnameToOperatingSystemPath(pathname) {
if (pathname[0] !== "/") throw new Error("pathname must start with /, got ".concat(pathname));
var pathnameWithoutLeadingSlash = pathname.slice(1);
const pathnameToOperatingSystemPath = pathname => {
if (pathname[0] !== "/") throw new Error(`pathname must start with /, got ${pathname}`);
const pathnameWithoutLeadingSlash = pathname.slice(1);

@@ -550,42 +619,40 @@ if (startsWithWindowsDriveLetter(pathnameWithoutLeadingSlash) && pathnameWithoutLeadingSlash[2] === "/") {

var resolveImportForProject = function resolveImportForProject(_ref) {
var projectPathname = _ref.projectPathname,
specifier = _ref.specifier,
_ref$importer = _ref.importer,
importer = _ref$importer === void 0 ? projectPathname : _ref$importer,
importMap = _ref.importMap,
importDefaultExtension = _ref.importDefaultExtension,
_ref$httpResolutionFo = _ref.httpResolutionForcing,
httpResolutionForcing = _ref$httpResolutionFo === void 0 ? true : _ref$httpResolutionFo,
_ref$httpResolutionOr = _ref.httpResolutionOrigin,
httpResolutionOrigin = _ref$httpResolutionOr === void 0 ? "http://fake_origin_unlikely_to_collide.ext" : _ref$httpResolutionOr,
_ref$insideProjectFor = _ref.insideProjectForcing,
insideProjectForcing = _ref$insideProjectFor === void 0 ? true : _ref$insideProjectFor;
const pathnameToRelativePath = (pathname, otherPathname) => pathname.slice(otherPathname.length);
const resolveImportForProject = ({
projectPathname,
specifier,
importer = projectPathname,
importMap,
importDefaultExtension,
httpResolutionForcing = true,
httpResolutionOrigin = "http://fake_origin_unlikely_to_collide.ext",
insideProjectForcing = true
}) => {
if (typeof projectPathname !== "string") {
throw new TypeError("projectPathname must be a string, got ".concat(projectPathname));
throw new TypeError(`projectPathname must be a string, got ${projectPathname}`);
}
var projectHref = "file://".concat(projectPathname);
var importerHref = importer || projectHref;
const projectHref = `file://${projectPathname}`;
const importerHref = importer || projectHref;
if (insideProjectForcing && importer !== projectHref && hrefUseFileProtocol(importerHref) && !importerHref.startsWith("".concat(projectHref, "/"))) {
throw new Error(createImporterMustBeInsideProjectMessage({
projectPathname: projectPathname,
importer: importer
if (insideProjectForcing && importer !== projectHref && hrefUseFileProtocol(importerHref) && !importerHref.startsWith(`${projectHref}/`)) {
throw new Error(formulateImporterMustBeInsideProject({
projectPathname,
importer
}));
}
var importerForProject;
let importerForProject;
if (httpResolutionForcing) {
if (importerHref === projectHref) {
importerForProject = "".concat(httpResolutionOrigin);
} else if (importerHref.startsWith("".concat(projectHref, "/"))) {
var importerPathname = hrefToPathname(importerHref);
var importerRelativePath = pathnameToRelativePath(importerPathname, projectPathname); // 99% of the time importer is an operating system path
importerForProject = `${httpResolutionOrigin}`;
} else if (importerHref.startsWith(`${projectHref}/`)) {
const importerPathname = hrefToPathname(importerHref);
const importerRelativePath = pathnameToRelativePath(importerPathname, projectPathname); // 99% of the time importer is an operating system path
// here we ensure / is resolved against project by forcing an url resolution
// prefixing with origin
importerForProject = "".concat(httpResolutionOrigin).concat(importerRelativePath);
importerForProject = `${httpResolutionOrigin}${importerRelativePath}`;
} else {

@@ -600,6 +667,6 @@ // there is already a scheme (http, https, file), keep it

var importResolved = resolveImport({
specifier: specifier,
const importResolved = resolveImport({
specifier,
importer: importerForProject,
importMap: importMap,
importMap,
defaultExtension: importDefaultExtension

@@ -610,8 +677,8 @@ });

// it's ok to have an external import like "https://cdn.com/jquery.js"
hrefUseFileProtocol(importResolved) && importResolved !== projectHref && !importResolved.startsWith("".concat(projectHref, "/"))) {
throw new Error(createImportMustBeInsideProjectMessage({
projectPathname: projectPathname,
specifier: specifier,
importer: importer,
importResolved: importResolved
hrefUseFileProtocol(importResolved) && importResolved !== projectHref && !importResolved.startsWith(`${projectHref}/`)) {
throw new Error(formulateImportMustBeInsideProject({
projectPathname,
specifier,
importer,
importResolved
}));

@@ -621,4 +688,4 @@ }

if (httpResolutionForcing && hrefToOrigin(importResolved) === httpResolutionOrigin) {
var importRelativePath = hrefToPathname(importResolved);
return "".concat(projectHref).concat(importRelativePath);
const importRelativePath = hrefToPathname(importResolved);
return `${projectHref}${importRelativePath}`;
}

@@ -629,30 +696,34 @@

var hrefUseFileProtocol = function hrefUseFileProtocol(specifier) {
return specifier.startsWith("file://");
};
const hrefUseFileProtocol = specifier => specifier.startsWith("file://");
var createImporterMustBeInsideProjectMessage = function createImporterMustBeInsideProjectMessage(_ref2) {
var projectPathname = _ref2.projectPathname,
importer = _ref2.importer;
return "importer must be inside project.\n --- importer ---\n ".concat(importer, "\n --- project ---\n ").concat(pathnameToOperatingSystemPath(projectPathname));
};
const formulateImporterMustBeInsideProject = ({
projectPathname,
importer
}) => `importer must be inside project.
--- importer ---
${importer}
--- project ---
${pathnameToOperatingSystemPath(projectPathname)}`;
var createImportMustBeInsideProjectMessage = function createImportMustBeInsideProjectMessage(_ref3) {
var projectPathname = _ref3.projectPathname,
specifier = _ref3.specifier,
importer = _ref3.importer,
importResolved = _ref3.importResolved;
return "import must be inside project.\n--- specifier ---\n".concat(specifier, "\n--- importer ---\n").concat(importer, "\n--- resolved import ---\n").concat(importResolved, "\n--- project path ---\n").concat(pathnameToOperatingSystemPath(projectPathname));
};
const formulateImportMustBeInsideProject = ({
projectPathname,
specifier,
importer,
importResolved
}) => `import must be inside project.
--- specifier ---
${specifier}
--- importer ---
${importer}
--- resolved import ---
${importResolved}
--- project path ---
${pathnameToOperatingSystemPath(projectPathname)}`;
var resolveSpecifierForProject = function resolveSpecifierForProject(_ref) {
var projectPathname = _ref.projectPathname,
specifier = _ref.specifier,
_ref$httpResolutionOr = _ref.httpResolutionOrigin,
httpResolutionOrigin = _ref$httpResolutionOr === void 0 ? "http://fake_origin_unlikely_to_collide.ext" : _ref$httpResolutionOr;
var specifierHttpResolved = resolveSpecifier(specifier, httpResolutionOrigin);
const resolveSpecifierForProject = (specifier, projectPathname, httpResolutionOrigin = "http://fake_origin_unlikely_to_collide.ext") => {
const specifierHttpResolved = resolveSpecifier(specifier, httpResolutionOrigin);
if (hrefToOrigin(specifierHttpResolved) === httpResolutionOrigin) {
var specifierRelativePath = hrefToPathname(specifierHttpResolved);
return "file://".concat(projectPathname).concat(specifierRelativePath);
const specifierRelativePath = hrefToPathname(specifierHttpResolved);
return `file://${projectPathname}${specifierRelativePath}`;
}

@@ -663,15 +734,42 @@

var wrapImportMap = function wrapImportMap(importMap, folderRelativeName) {
/**
* wrapImportMap can be used to remap all your imports under a folder.
*
* It is used by jsenv to import from a compiled folder instead of source folder.
*
* wrapImportMap must preserve the import map order so that
* applyImportMap can still match the most specific pattern first.
*
* Because order is directly connected to the pattern length
* prefixing every pattern with something does not means we have to sort
* the wrappedImportMap.
*
* However we must absolutely ensure if an import like '/' exists in imports
* or scoped imports. It must remain the last when being prefixed.
*
*/
const wrapImportMap = (importMap, folderRelativeName, ensureInto = true) => {
assertImportMap(importMap);
if (typeof folderRelativeName !== "string") {
throw new TypeError("folderRelativeName must be a string, got ".concat(folderRelativeName));
throw new TypeError(formulateFolderRelativeNameMustBeAString({
folderRelativeName
}));
}
var into = "/".concat(folderRelativeName, "/");
var imports = importMap.imports,
scopes = importMap.scopes;
var importsForWrapping;
var scopesForWrapping;
const into = `/${folderRelativeName}/`;
const {
imports,
scopes
} = importMap;
let importsForWrapping;
if (imports) {
importsForWrapping = wrapTopLevelImports(imports, into);
} else {
importsForWrapping = {};
}
let scopesForWrapping;
if (scopes) {

@@ -683,16 +781,12 @@ scopesForWrapping = wrapScopes(scopes, into);

if (imports) {
importsForWrapping = wrapTopLevelImports(imports, into);
scopesForWrapping[into] = wrapTopLevelImports(imports, into);
} else {
importsForWrapping = {};
scopesForWrapping[into] = {};
} // ensure anything not directly remapped is remapped inside into
if (ensureInto) {
// ensure anything not directly remapped is remapped inside into
importsForWrapping[into] = into;
importsForWrapping["/"] = into; // and when already into, you stay inside
scopesForWrapping[into] = {
[into]: into
};
}
importsForWrapping[into] = into;
importsForWrapping["/"] = into; // and when already into, you stay inside
scopesForWrapping[into][into] = into;
scopesForWrapping[into]["/"] = into;
return {

@@ -704,99 +798,135 @@ imports: importsForWrapping,

var wrapScopes = function wrapScopes(scopes, into) {
var scopesKeyWrapped = {};
var scopesRemaining = {};
Object.keys(scopes).forEach(function (scopeKey) {
var scopeValue = scopes[scopeKey];
var scopeKeyWrapped = wrapSpecifier(scopeKey, into);
const wrapScopes = (scopes, into) => {
const scopesWrapped = {};
Object.keys(scopes).forEach(scopeKey => {
const scopeValue = scopes[scopeKey];
const scopeKeyWrapped = wrapAddress(scopeKey, into);
const {
importsWrapped,
importsRemaining
} = wrapImports(scopeValue, into);
let scopeValueWrapped;
if (scopeKeyWrapped === scopeKey) {
scopesRemaining[scopeKey] = scopeValue;
} else {
var _wrapImports = wrapImports(scopeValue, into),
importsWithKeyWrapped = _wrapImports.importsWithKeyWrapped,
importsRemaining = _wrapImports.importsRemaining;
if (scopeHasLeadingSlashScopedRemapping(scopeValue, scopeKey)) {
const leadingSlashSpecifier = `${into}${scopeKey.slice(1)}`;
scopeValueWrapped = {}; // put everything except the leading slash remapping
var scopeValueWrapped;
Object.keys(importsWrapped).forEach(importKeyWrapped => {
if (importKeyWrapped === leadingSlashSpecifier || importKeyWrapped === into) {
return;
}
if (scopeHasLeadingSlashScopedRemapping(scopeValue, scopeKey)) {
var leadingSlashSpecifier = "".concat(into).concat(scopeKey.slice(1));
scopeValueWrapped = {}; // put everything except the leading slash remapping
scopeValueWrapped[importKeyWrapped] = importsWrapped[importKeyWrapped];
});
Object.keys(importsRemaining).forEach(importKey => {
if (importKey === scopeKey || importKey === "/") {
return;
}
Object.keys(importsWithKeyWrapped).forEach(function (importKeyWrapped) {
if (importKeyWrapped === leadingSlashSpecifier || importKeyWrapped === into) {
return;
}
scopeValueWrapped[importKey] = importsRemaining[importKey];
}); // now put leading slash remapping to ensure it comes last
scopeValueWrapped[importKeyWrapped] = importsWithKeyWrapped[importKeyWrapped];
});
Object.keys(importsRemaining).forEach(function (importKey) {
if (importKey === scopeKey || importKey === "/") {
return;
}
scopeValueWrapped[leadingSlashSpecifier] = leadingSlashSpecifier;
scopeValueWrapped[scopeKey] = leadingSlashSpecifier;
scopeValueWrapped[into] = leadingSlashSpecifier;
scopeValueWrapped["/"] = leadingSlashSpecifier;
} else {
scopeValueWrapped = { ...importsWrapped,
...importsRemaining
};
}
scopeValueWrapped[importKey] = importsRemaining[importKey];
}); // now put leading slash remapping to ensure it comes last
scopesWrapped[scopeKeyWrapped] = scopeValueWrapped;
scopeValueWrapped[leadingSlashSpecifier] = leadingSlashSpecifier;
scopeValueWrapped[scopeKey] = leadingSlashSpecifier;
scopeValueWrapped[into] = leadingSlashSpecifier;
scopeValueWrapped["/"] = leadingSlashSpecifier;
} else {
scopeValueWrapped = _objectSpread({}, importsWithKeyWrapped, {}, importsRemaining);
}
scopesKeyWrapped[scopeKeyWrapped] = scopeValueWrapped;
scopesRemaining[scopeKey] = importsRemaining;
if (scopeKeyWrapped !== scopeKey) {
scopesWrapped[scopeKey] = { ...scopeValueWrapped
};
}
});
return _objectSpread({}, scopesKeyWrapped, {}, scopesRemaining);
return scopesWrapped;
};
var scopeHasLeadingSlashScopedRemapping = function scopeHasLeadingSlashScopedRemapping(scopeImports, scopeKey) {
const scopeHasLeadingSlashScopedRemapping = (scopeImports, scopeKey) => {
return scopeKey in scopeImports && scopeImports[scopeKey] === scopeKey && "/" in scopeImports && scopeImports["/"] === scopeKey;
};
var wrapImports = function wrapImports(imports, into) {
var importsWithKeyWrapped = {};
var importsRemaining = {};
Object.keys(imports).forEach(function (importKey) {
var importValue = imports[importKey];
var importKeyWrapped = wrapSpecifier(importKey, into);
var importValueWrapped = wrapSpecifier(importValue, into);
const wrapImports = (imports, into) => {
const importsWrapped = {};
const importsRemaining = {};
Object.keys(imports).forEach(importKey => {
const importValue = imports[importKey];
const importKeyWrapped = wrapSpecifier(importKey, into);
const importValueWrapped = wrapAddress(importValue, into);
const keyChanged = importKeyWrapped !== importKey;
const valueChanged = importValueWrapped !== importValue;
if (importKeyWrapped === importKey) {
if (keyChanged || valueChanged) {
importsWrapped[importKeyWrapped] = importValueWrapped;
} else {
importsRemaining[importKey] = importValue;
} else if (importValueWrapped === importValue) {
importsWithKeyWrapped[importKeyWrapped] = importValue;
} else {
importsWithKeyWrapped[importKeyWrapped] = importValueWrapped;
importsRemaining[importKey] = importValueWrapped;
}
});
return {
importsWithKeyWrapped: importsWithKeyWrapped,
importsRemaining: importsRemaining
importsWrapped,
importsRemaining
};
};
var wrapTopLevelImports = function wrapTopLevelImports(imports, into) {
var _wrapImports2 = wrapImports(imports, into),
importsWithKeyWrapped = _wrapImports2.importsWithKeyWrapped,
importsRemaining = _wrapImports2.importsRemaining;
return _objectSpread({}, importsWithKeyWrapped, {}, importsRemaining);
const wrapTopLevelImports = (imports, into) => {
const {
importsWrapped,
importsRemaining
} = wrapImports(imports, into);
return { ...importsWrapped,
...importsRemaining
};
};
var wrapSpecifier = function wrapSpecifier(specifier, into) {
if (isOriginRelativeSpecifier(specifier)) {
return "".concat(into).concat(specifier.slice(1));
const wrapSpecifier = (specifier, into) => {
if (specifier.startsWith("//")) {
return specifier;
}
if (isBareSpecifier(specifier)) {
return "".concat(into).concat(specifier);
if (specifier[0] === "/") {
return `${into}${specifier.slice(1)}`;
}
if (specifier.startsWith("./")) {
return `./${into}${specifier.slice(2)}`;
}
return specifier;
};
const wrapAddress = (string, into) => {
if (string.startsWith("//")) {
return string;
}
if (string[0] === "/") {
return `${into}${string.slice(1)}`;
}
if (string.startsWith("./")) {
return `./${into}${string.slice(2)}`;
}
if (string.startsWith("../")) {
return string;
}
if (hasScheme(string)) {
return string;
} // bare
return `${into}${string}`;
};
const formulateFolderRelativeNameMustBeAString = ({
folderRelativeName
}) => `folderRelativeName must be a string.
--- folder relative name ---
${folderRelativeName}`;
exports.applyImportMap = applyImportMap;

@@ -810,4 +940,5 @@ exports.composeTwoImportMaps = composeTwoImportMaps;

exports.resolveSpecifierForProject = resolveSpecifierForProject;
exports.resolveUrl = resolveUrl;
exports.sortImportMap = sortImportMap;
exports.wrapImportMap = wrapImportMap;
//# sourceMappingURL=main.js.map

@@ -13,3 +13,4 @@ export { applyImportMap } from "./src/applyImportMap/applyImportMap.js"

} from "./src/resolveSpecifierForProject/resolveSpecifierForProject.js"
export { resolveUrl } from "./src/resolveUrl/resolveUrl.js"
export { sortImportMap } from "./src/sortImportMap/sortImportMap.js"
export { wrapImportMap } from "./src/wrapImportMap/wrapImportMap.js"
{
"name": "@jsenv/import-map",
"version": "5.5.0",
"description": "Helpers to implement importMap",
"version": "6.2.0",
"license": "MIT",

@@ -9,4 +10,8 @@ "repository": {

},
"engines": {
"node": ">=12.0.0"
},
"publishConfig": {
"access": "public"
"access": "public",
"registry": "https://registry.npmjs.org"
},

@@ -21,3 +26,3 @@ "main": "dist/commonjs/main.js",

"exports": {
"/": "/"
"./": "./"
},

@@ -39,19 +44,19 @@ "scripts": {

"dependencies": {
"@jsenv/href": "1.0.0"
"@jsenv/href": "1.2.0",
"@jsenv/operating-system-path": "2.7.0"
},
"devDependencies": {
"@dmail/assert": "3.14.0",
"@jsenv/bundling": "5.15.0",
"@jsenv/codecov-upload": "1.8.0",
"@jsenv/eslint-config": "10.0.0",
"@jsenv/execution": "5.11.0",
"@jsenv/node-launcher": "4.15.0",
"@jsenv/node-module-import-map": "7.0.0",
"@jsenv/operating-system-path": "2.4.0",
"@jsenv/prettier-config": "1.0.0",
"@jsenv/prettier-check-project": "3.3.0",
"@jsenv/url-meta": "2.0.0",
"@jsenv/testing": "3.2.0",
"@jsenv/auto-publish": "1.9.0",
"@jsenv/bundling": "7.6.2",
"@jsenv/codecov-upload": "2.0.0",
"@jsenv/eslint-config": "10.2.0",
"@jsenv/execution": "6.11.0",
"@jsenv/node-launcher": "4.26.0",
"@jsenv/node-module-import-map": "8.2.1",
"@jsenv/prettier-config": "1.0.1",
"@jsenv/prettier-check-project": "3.5.0",
"@jsenv/testing": "3.9.0",
"babel-eslint": "11.0.0-beta.0",
"eslint": "6.4.0",
"eslint": "6.5.1",
"prettier": "1.18.2",

@@ -58,0 +63,0 @@ "rimraf": "3.0.0"

# jsenv-import-map
> importMap programmatic implementation
[![github package](https://img.shields.io/github/package-json/v/jsenv/jsenv-import-map.svg?logo=github&label=package)](https://github.com/jsenv/jsenv-import-map/packages)
[![npm package](https://img.shields.io/npm/v/@jsenv/import-map.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/import-map)
[![github ci](https://github.com/jsenv/jsenv-import-map/workflows/ci/badge.svg)](https://github.com/jsenv/jsenv-import-map/actions?workflow=ci)
[![codecov coverage](https://codecov.io/gh/jsenv/jsenv-import-map/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/jsenv-import-map)
[![github package](https://img.shields.io/github/package-json/v/jsenv/jsenv-import-map.svg?label=package&logo=github)](https://github.com/jsenv/jsenv-import-map/packages)
[![ci status](https://github.com/jsenv/jsenv-import-map/workflows/ci/badge.svg)](https://github.com/jsenv/jsenv-import-map/actions)
[![codecov](https://codecov.io/gh/jsenv/jsenv-import-map/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/jsenv-import-map)
Helpers to implement importMap
## Introduction
## Table of contents
`jsenv-import-map` is a javasScript implementation of the importMap specification. It is written using es modules and is compatible with Node.js.<br />
- [Presentation](#Presentation)
- [Usage](#Usage)
- [composeTwoImportMaps](#composetwoimportmaps)
- [normalizeImportMap](#normalizeimportmap)
- [resolveImport](#resolveimport)
- [Installation](#installation)
I made this project because jsenv uses importMap but they are not yet available in browsers.<br />
## Presentation
`@jsenv/import-map` can be used to implement the behaviour of importMap as described in the specification. It is written using es modules and is compatible with Node.js.<br />
— see [importMap spec](https://github.com/WICG/import-maps)
`@jsenv/import-map` has the following exports:
## Usage
- [applyImportMap](#applyimportmap)
- [composeTwoImportMaps](#composetwoimportmaps)
- [normalizeImportMap](#normalizeimportmap)
- [resolveImport](#resolveimport)
- [resolveSpecifier](#resolvespecifier)
- [wrapImportMap](#wrapimportmap)
`@jsenv/import-map` exports are documented in this section.
## applyImportMap
### composeTwoImportMaps
> takes { `importMap`, `href`, `importerHref` } and returns either the `href` remapped by `importMap` or the original `href`.
> `composeTwoImportMaps` takes two `importMap` and return a single `importMap` being the composition of the two.<br />
> Implemented by [src/composeTwoImportMaps/composeTwoImportMaps.js](src/composeTwoImportMaps/composeTwoImportMaps.js)
```js
import { applyImportMap } from "@jsenv/import-map"
const href = "http://domain.com/foo"
const importMap = {
imports: {
"http://domain.com/foo": "http://domain.com/bar",
},
}
const hrefRemapped = applyImportMap({
href,
importMap,
})
console.log(hrefRemapped)
```
The code above logs `"http://domain.com/bar"`.<br />
The provided `importMap` specifiers must be absolute and sorted to work as expected.<br />
You can use [normalizeImportMap](#normalizeimportmap) to do that.<br />
— see [applyImportMap source code](./src/applyImportMap/applyImportMap.js)
## composeTwoImportMaps
> takes (`leftImportMap`, `rightImportMap`) and returns an importMap being the composition of the two.
```js
import { composeTwoImportMaps } from "@jsenv/import-map"
const leftImportMap = {
imports: {
foo: "bar",
const importMap = composeTwoImportMaps(
{
imports: {
foo: "bar",
},
},
}
const rightImportMap = {
imports: {
foo: "whatever",
{
imports: {
foo: "whatever",
},
},
}
const importMap = composeTwoImportMaps(leftImportMap, rightImportMap)
)
console.log(importMap.imports.foo)
console.log(JSON.stringify(importMap, null, " "))
```
The code above logs `"whatever"`.
```console
{
"imports": {
"foo": "whatever"
}
}
```
— see [composeTwoImportMaps source code](./src/composeTwoImportMaps/composeTwoImportMaps.js)
### normalizeImportMap
## normalizeImportMap
> `normalizeImportMap` returns an `importMap` resolved against an `url` and sorted.<br />
> Implemented by [src/normalizeImportMap/normalizeImportMap.js](src/normalizeImportMap/normalizeImportMap.js)
> takes (`importMap`, `href`) and returns an importMap where relative specifier are resolved against `href` and sorted.
```js
import { normalizeImportMap } from "@jsenv/import-map"
const importMap = {
imports: {
foo: "http://cdndomain.com/bar",
const importMap = normalizeImportMap(
{
imports: {
foo: "./bar",
"./ding.js": "./dong.js"
},
},
}
const href = "http://mydomain.com"
const importMapNormalized = normalizeImportMap(importMap, href)
"http://your-domain.com",
)
console.log(importMapNormalized.imports["http://mydomain.com/foo"])
console.log(JSON.stringify(importMap, null, ' ')
```
The code above logs `"http://cdndomain.com/bar"`.
```console
{
"imports": {
"foo": "http://your-domain.com/bar",
"http://your-domain.com/ding.js": "http://your-domain.com/dong.js"
}
}
```
— see [normalizeImportMap source code](./src/normalizeImportMap/normalizeImportMap.js)
### resolveImport
## resolveImport
> `resolveImport` returns an import `url` applying an `importMap` to `specifier` and `importer`.<br />
> Implemented by [src/resolveImport/resolveImport.js](src/resolveImport/resolveImport.js)
> takes { `specifier`, `importer`, `importMap`, `defaultExtension` } and returns a url.
```js

@@ -120,83 +112,20 @@ import { resolveImport } from "@jsenv/import-map"

The code above logs `"http://domain.com/main.js"`.
— see [resolveImport source code](./src/resolveImport/resolveImport.js)
## resolveSpecifier
> takes (`specifier`, `importer`) and returns `specifier` resolved against `importer`.
```js
import { resolveSpecifier } from "@jsenv/import-map"
const specifier = "../file.js"
const importer = "http://mydomain.com/folder/index.js"
const specifierResolved = resolveSpecifier(specifier, importer)
console.log(specifierResolved)
```
The code above logs `"http://mydomain.com/file.js"`.
— see [resolveSpecifier source code](./src/resolveSpecifier/resolveSpecifier.js)
## wrapImportMap
> takes (`importMap`, `folderRelativeName`) and returns an importMap wrapped inside `folderRelativeName`.
```js
import { wrapImportMap } from "@jsenv/import-map"
const importMap = {
imports: {
foo: "bar",
},
}
const folderRelativeName = "/dist"
const importMapWrapped = wrapImportMap(specifier, importer)
console.log(importMapWrapped.imports.foo)
```
The code above logs `"/dist/bar"`.<br />
This feature is not part of the spec but is usefull to redirect your imports inside a given folder.<br />
— see [wrapImportMap source code](./src/wrapImportMap/wrapImportMap.js)
## Installation using npm
To install `@jsenv/import-map` you need to configure npm to use github registry for this package.
1. Configure npm authentification
Github registry requires an authentification token. If you haven't configured it already, read how in the documentation below.<br />
— see [Authenticating to GitHub Package Registry documentation on GitHub](https://help.github.com/en/articles/configuring-npm-for-use-with-github-package-registry#authenticating-to-github-package-registry)
For the record, you can save your token with this command
```console
npm config set '//npm.pkg.github.com/:_authToken' 'personal-access-token'
http://domain.com/main.js
```
2. Configure npm registry
The provided `importMap` must be resolved and sorted to work as expected. You can use [normalizeImportMap](#normalizeimportmap) to do that.<br />
Run the command below to use github registry for `@jsenv/import-map`
## Installation
```console
npm config set @jsenv:registry https://npm.pkg.github.com
```
If you never installed a jsenv package, read [Installing a jsenv package](https://github.com/jsenv/jsenv-core/blob/master/docs/installing-jsenv-package.md#installing-a-jsenv-package) before going further.
3. Run install command
This documentation is up-to-date with a specific version so prefer any of the following commands
```console
npm install @jsenv/import-map@5.2.0
npm install --save-dev @jsenv/import-map@6.2.0
```
### Installation using yarn
Same steps as [Installation using npm](#installation-using-npm) replacing step 3 by
```console
yarn add @jsenv/import-map@5.2.0
yarn add --dev @jsenv/import-map@6.2.0
```
import { assertImportMap } from "../assertImportMap.js"
import { assertUrlLike } from "../assertUrlLike.js"
import { hasScheme } from "../hasScheme.js"
import { tryUrlResolution } from "../tryUrlResolution.js"
import { resolveSpecifier } from "../resolveSpecifier/resolveSpecifier.js"
export const applyImportMap = ({ importMap, href, importerHref }) => {
export const applyImportMap = ({ importMap, specifier, importer }) => {
assertImportMap(importMap)
assertUrlLike(href, "href")
if (importerHref) {
assertUrlLike(importerHref, "importerHref")
if (typeof specifier !== "string") {
throw new TypeError(writeSpecifierMustBeAString({ specifier, importer }))
}
if (importer) {
if (typeof importer !== "string") {
throw new TypeError(writeImporterMustBeAString({ importer, specifier }))
}
if (!hasScheme(importer)) {
throw new Error(writeImporterMustBeAbsolute({ importer, specifier }))
}
}
const specifierUrl = resolveSpecifier(specifier, importer)
const specifierNormalized = specifierUrl || specifier
const { scopes } = importMap
if (scopes && importerHref) {
if (scopes && importer) {
const scopeKeyMatching = Object.keys(scopes).find((scopeKey) => {
return scopeKey === importerHref || specifierIsPrefixOf(scopeKey, importerHref)
return scopeKey === importer || specifierIsPrefixOf(scopeKey, importer)
})
if (scopeKeyMatching) {
const scopeValue = scopes[scopeKeyMatching]
const remappingFromScopeImports = applyImports(href, scopeValue)
const remappingFromScopeImports = applyImports(specifierNormalized, scopeValue)
if (remappingFromScopeImports !== null) {

@@ -27,3 +39,3 @@ return remappingFromScopeImports

if (imports) {
const remappingFromImports = applyImports(href, imports)
const remappingFromImports = applyImports(specifierNormalized, imports)
if (remappingFromImports !== null) {

@@ -34,6 +46,10 @@ return remappingFromImports

return href
if (specifierUrl) {
return specifierUrl
}
throw new Error(writeBareSpecifierMustBeRemapped({ specifier, importer }))
}
const applyImports = (href, imports) => {
const applyImports = (specifier, imports) => {
const importKeyArray = Object.keys(imports)

@@ -45,10 +61,11 @@

i++
if (importKey === href) {
if (importKey === specifier) {
const importValue = imports[importKey]
return importValue
}
if (specifierIsPrefixOf(importKey, href)) {
if (specifierIsPrefixOf(importKey, specifier)) {
const importValue = imports[importKey]
const afterImportKey = href.slice(importKey.length)
return importValue + afterImportKey
const afterImportKey = specifier.slice(importKey.length)
return tryUrlResolution(afterImportKey, importValue)
}

@@ -63,1 +80,25 @@ }

}
const writeSpecifierMustBeAString = ({ specifier, importer }) => `specifier must be a string.
--- specifier ---
${specifier}
--- importer ---
${importer}`
const writeImporterMustBeAString = ({ importer, specifier }) => `importer must be a string.
--- importer ---
${importer}
--- specifier ---
${specifier}`
const writeImporterMustBeAbsolute = ({ importer, specifier }) => `importer must be an absolute url.
--- importer ---
${importer}
--- specifier ---
${specifier}`
const writeBareSpecifierMustBeRemapped = ({ specifier, importer }) => `Unmapped bare specifier.
--- specifier ---
${specifier}
--- importer ---
${importer}`
import { assertImportMap } from "../assertImportMap.js"
import { tryUrlResolution } from "../tryUrlResolution.js"
import { resolveSpecifier } from "../resolveSpecifier/resolveSpecifier.js"
import { sortImports, sortScopes } from "../sortImportMap/sortImportMap.js"
export const normalizeImportMap = (importMap, href) => {
export const normalizeImportMap = (importMap, baseUrl) => {
assertImportMap(importMap)
if (typeof href !== "string") {
throw new TypeError(`href must be a string, got ${href}`)
if (typeof baseUrl !== "string") {
throw new TypeError(formulateBaseUrlMustBeAString({ baseUrl }))
}

@@ -14,14 +16,47 @@

return {
imports: imports ? normalizeImports(imports, href) : undefined,
scopes: scopes ? normalizeScopes(scopes, href) : undefined,
imports: imports ? normalizeImports(imports, baseUrl) : undefined,
scopes: scopes ? normalizeScopes(scopes, baseUrl) : undefined,
}
}
const normalizeImports = (imports, href) => {
const normalizeImports = (imports, baseUrl) => {
const importsNormalized = {}
Object.keys(imports).forEach((importKey) => {
const importValue = imports[importKey]
const importKeyNormalized = resolveSpecifier(importKey, href)
const importValueNormalized = resolveSpecifier(importValue, href)
importsNormalized[importKeyNormalized] = importValueNormalized
Object.keys(imports).forEach((specifier) => {
const address = imports[specifier]
if (typeof address !== "string") {
console.warn(
formulateAddressMustBeAString({
address,
specifier,
}),
)
return
}
const specifierResolved = resolveSpecifier(specifier, baseUrl) || specifier
const addressUrl = tryUrlResolution(address, baseUrl)
if (addressUrl === null) {
console.warn(
formulateAdressResolutionFailed({
address,
baseUrl,
specifier,
}),
)
return
}
if (specifier.endsWith("/") && !addressUrl.endsWith("/")) {
console.warn(
formulateAddressUrlRequiresTrailingSlash({
addressUrl,
address,
specifier,
}),
)
return
}
importsNormalized[specifierResolved] = addressUrl
})

@@ -31,11 +66,60 @@ return sortImports(importsNormalized)

const normalizeScopes = (scopes, href) => {
const normalizeScopes = (scopes, baseUrl) => {
const scopesNormalized = {}
Object.keys(scopes).forEach((scopeKey) => {
const scopeValue = scopes[scopeKey]
const scopeKeyNormalized = resolveSpecifier(scopeKey, href)
const scopeValueNormalized = normalizeImports(scopeValue, href)
scopesNormalized[scopeKeyNormalized] = scopeValueNormalized
Object.keys(scopes).forEach((scope) => {
const scopeValue = scopes[scope]
const scopeUrl = tryUrlResolution(scope, baseUrl)
if (scopeUrl === null) {
console.warn(
formulateScopeResolutionFailed({
scope,
baseUrl,
}),
)
return
}
const scopeValueNormalized = normalizeImports(scopeValue, baseUrl)
scopesNormalized[scopeUrl] = scopeValueNormalized
})
return sortScopes(scopesNormalized)
}
const formulateBaseUrlMustBeAString = ({ baseUrl }) => `baseUrl must be a string.
--- base url ---
${baseUrl}`
const formulateAddressMustBeAString = ({ specifier, address }) => `Address must be a string.
--- address ---
${address}
--- specifier ---
${specifier}`
const formulateAdressResolutionFailed = ({
address,
baseUrl,
specifier,
}) => `Address url resolution failed.
--- address ---
${address}
--- base url ---
${baseUrl}
--- specifier ---
${specifier}`
const formulateAddressUrlRequiresTrailingSlash = ({
addressURL,
address,
specifier,
}) => `Address must end with /.
--- address url ---
${addressURL}
--- address ---
${address}
--- specifier ---
${specifier}`
const formulateScopeResolutionFailed = ({ scope, baseUrl }) => `Scope url resolution failed.
--- scope ---
${scope}
--- base url ---
${baseUrl}`

@@ -7,27 +7,33 @@ // directly target the files because this code

import { pathnameToExtension } from "@jsenv/href/src/pathnameToExtension/pathnameToExtension.js"
import { resolveSpecifier } from "../resolveSpecifier/resolveSpecifier.js"
import { resolveUrl } from "../resolveUrl/resolveUrl.js"
import { applyImportMap } from "../applyImportMap/applyImportMap.js"
export const resolveImport = ({ specifier, importer, importMap, defaultExtension = true }) => {
const specifierResolved = resolveSpecifier(specifier, importer)
const specifierRemapped = importMap
? applyImportMap({ importMap, href: specifierResolved, importerHref: importer })
: specifierResolved
return applyDefaultExtension({
url: importMap
? applyImportMap({ importMap, specifier, importer })
: resolveUrl(specifier, importer),
importer,
defaultExtension,
})
}
const applyDefaultExtension = ({ url, importer, defaultExtension }) => {
if (typeof defaultExtension === "string") {
const extension = pathnameToExtension(specifierRemapped)
const extension = pathnameToExtension(url)
if (extension === "") {
return `${specifierRemapped}${defaultExtension}`
return `${url}${defaultExtension}`
}
return url
}
if (defaultExtension === true) {
const extension = pathnameToExtension(specifierRemapped)
if (extension === "") {
if (importer) {
const importerPathname = hrefToPathname(importer)
const importerExtension = pathnameToExtension(importerPathname)
return `${specifierRemapped}${importerExtension}`
}
const extension = pathnameToExtension(url)
if (extension === "" && importer) {
const importerPathname = hrefToPathname(importer)
const importerExtension = pathnameToExtension(importerPathname)
return `${url}${importerExtension}`
}
}
return specifierRemapped
return url
}

@@ -29,3 +29,3 @@ import { pathnameToOperatingSystemPath } from "@jsenv/operating-system-path"

throw new Error(
createImporterMustBeInsideProjectMessage({
formulateImporterMustBeInsideProject({
projectPathname,

@@ -73,3 +73,3 @@ importer,

throw new Error(
createImportMustBeInsideProjectMessage({
formulateImportMustBeInsideProject({
projectPathname,

@@ -93,12 +93,12 @@ specifier,

const createImporterMustBeInsideProjectMessage = ({
const formulateImporterMustBeInsideProject = ({
projectPathname,
importer,
}) => `importer must be inside project.
--- importer ---
${importer}
--- project ---
${pathnameToOperatingSystemPath(projectPathname)}`
--- importer ---
${importer}
--- project ---
${pathnameToOperatingSystemPath(projectPathname)}`
const createImportMustBeInsideProjectMessage = ({
const formulateImportMustBeInsideProject = ({
projectPathname,

@@ -105,0 +105,0 @@ specifier,

@@ -1,56 +0,14 @@

// could be useful: https://url.spec.whatwg.org/#url-miscellaneous
import { hasScheme } from "../hasScheme.js"
import { resolveUrl } from "../resolveUrl/resolveUrl.js"
import { isAbsoluteSpecifier, resolveAbsoluteSpecifier } from "./absoluteSpecifier.js"
import {
isSchemeRelativeSpecifier,
resolveSchemeRelativeSpecifier,
} from "./schemeRelativeSpecifier.js"
import {
isOriginRelativeSpecifier,
resolveOriginRelativeSpecifier,
} from "./originRelativeSpecifier.js"
import {
isPathnameRelativeSpecifier,
resolvePathnameRelativeSpecifier,
} from "./pathnameRelativeSpecifier.js"
import { resolveBareSpecifier } from "./bareSpecifier.js"
export const resolveSpecifier = (specifier, importer) => {
if (isAbsoluteSpecifier(specifier)) {
return resolveAbsoluteSpecifier(specifier, importer)
if (specifier[0] === "/" || specifier.startsWith("./") || specifier.startsWith("../")) {
return resolveUrl(specifier, importer)
}
if (!importer) {
throw new Error(createMissingImporterMessage(specifier, importer))
if (hasScheme(specifier)) {
return specifier
}
if (!isAbsoluteSpecifier(importer)) {
throw new Error(createAbsoluteImporterRequiredMessage(importer))
}
if (isSchemeRelativeSpecifier(specifier)) {
return resolveSchemeRelativeSpecifier(specifier, importer)
}
if (isOriginRelativeSpecifier(specifier)) {
return resolveOriginRelativeSpecifier(specifier, importer)
}
if (isPathnameRelativeSpecifier(specifier)) {
return resolvePathnameRelativeSpecifier(specifier, importer)
}
return resolveBareSpecifier(specifier, importer)
return null
}
const createMissingImporterMessage = (
specifier,
importer,
) => `missing importer to resolve relative specifier.
--- specifier ---
${specifier}
--- importer ---
${importer}`
const createAbsoluteImporterRequiredMessage = (importer) => `importer must be absolute.
--- importer ---
${importer}`
import { hrefToOrigin, hrefToPathname } from "@jsenv/href"
import { resolveSpecifier } from "../resolveSpecifier/resolveSpecifier.js"
export const resolveSpecifierForProject = ({
export const resolveSpecifierForProject = (
specifier,
projectPathname,
specifier,
httpResolutionOrigin = "http://fake_origin_unlikely_to_collide.ext",
}) => {
) => {
const specifierHttpResolved = resolveSpecifier(specifier, httpResolutionOrigin)

@@ -10,0 +10,0 @@ if (hrefToOrigin(specifierHttpResolved) === httpResolutionOrigin) {

@@ -18,10 +18,9 @@ /**

import { isOriginRelativeSpecifier } from "../resolveSpecifier/originRelativeSpecifier.js"
import { isBareSpecifier } from "../resolveSpecifier/bareSpecifier.js"
import { assertImportMap } from "../assertImportMap.js"
import { hasScheme } from "../hasScheme.js"
export const wrapImportMap = (importMap, folderRelativeName) => {
export const wrapImportMap = (importMap, folderRelativeName, ensureInto = true) => {
assertImportMap(importMap)
if (typeof folderRelativeName !== "string") {
throw new TypeError(`folderRelativeName must be a string, got ${folderRelativeName}`)
throw new TypeError(formulateFolderRelativeNameMustBeAString({ folderRelativeName }))
}

@@ -33,4 +32,9 @@

let importsForWrapping
if (imports) {
importsForWrapping = wrapTopLevelImports(imports, into)
} else {
importsForWrapping = {}
}
let scopesForWrapping
if (scopes) {

@@ -42,17 +46,10 @@ scopesForWrapping = wrapScopes(scopes, into)

if (imports) {
importsForWrapping = wrapTopLevelImports(imports, into)
scopesForWrapping[into] = wrapTopLevelImports(imports, into)
} else {
importsForWrapping = {}
scopesForWrapping[into] = {}
if (ensureInto) {
// ensure anything not directly remapped is remapped inside into
importsForWrapping[into] = into
importsForWrapping["/"] = into
// and when already into, you stay inside
scopesForWrapping[into] = { [into]: into }
}
// ensure anything not directly remapped is remapped inside into
importsForWrapping[into] = into
importsForWrapping["/"] = into
// and when already into, you stay inside
scopesForWrapping[into][into] = into
scopesForWrapping[into]["/"] = into
return {

@@ -65,51 +62,46 @@ imports: importsForWrapping,

const wrapScopes = (scopes, into) => {
const scopesKeyWrapped = {}
const scopesRemaining = {}
const scopesWrapped = {}
Object.keys(scopes).forEach((scopeKey) => {
const scopeValue = scopes[scopeKey]
const scopeKeyWrapped = wrapSpecifier(scopeKey, into)
const scopeKeyWrapped = wrapAddress(scopeKey, into)
if (scopeKeyWrapped === scopeKey) {
scopesRemaining[scopeKey] = scopeValue
} else {
const { importsWithKeyWrapped, importsRemaining } = wrapImports(scopeValue, into)
const { importsWrapped, importsRemaining } = wrapImports(scopeValue, into)
let scopeValueWrapped
if (scopeHasLeadingSlashScopedRemapping(scopeValue, scopeKey)) {
const leadingSlashSpecifier = `${into}${scopeKey.slice(1)}`
scopeValueWrapped = {}
// put everything except the leading slash remapping
Object.keys(importsWithKeyWrapped).forEach((importKeyWrapped) => {
if (importKeyWrapped === leadingSlashSpecifier || importKeyWrapped === into) {
return
}
scopeValueWrapped[importKeyWrapped] = importsWithKeyWrapped[importKeyWrapped]
})
Object.keys(importsRemaining).forEach((importKey) => {
if (importKey === scopeKey || importKey === "/") {
return
}
scopeValueWrapped[importKey] = importsRemaining[importKey]
})
// now put leading slash remapping to ensure it comes last
scopeValueWrapped[leadingSlashSpecifier] = leadingSlashSpecifier
scopeValueWrapped[scopeKey] = leadingSlashSpecifier
scopeValueWrapped[into] = leadingSlashSpecifier
scopeValueWrapped["/"] = leadingSlashSpecifier
} else {
scopeValueWrapped = {
...importsWithKeyWrapped,
...importsRemaining,
let scopeValueWrapped
if (scopeHasLeadingSlashScopedRemapping(scopeValue, scopeKey)) {
const leadingSlashSpecifier = `${into}${scopeKey.slice(1)}`
scopeValueWrapped = {}
// put everything except the leading slash remapping
Object.keys(importsWrapped).forEach((importKeyWrapped) => {
if (importKeyWrapped === leadingSlashSpecifier || importKeyWrapped === into) {
return
}
scopeValueWrapped[importKeyWrapped] = importsWrapped[importKeyWrapped]
})
Object.keys(importsRemaining).forEach((importKey) => {
if (importKey === scopeKey || importKey === "/") {
return
}
scopeValueWrapped[importKey] = importsRemaining[importKey]
})
// now put leading slash remapping to ensure it comes last
scopeValueWrapped[leadingSlashSpecifier] = leadingSlashSpecifier
scopeValueWrapped[scopeKey] = leadingSlashSpecifier
scopeValueWrapped[into] = leadingSlashSpecifier
scopeValueWrapped["/"] = leadingSlashSpecifier
} else {
scopeValueWrapped = {
...importsWrapped,
...importsRemaining,
}
}
scopesKeyWrapped[scopeKeyWrapped] = scopeValueWrapped
scopesRemaining[scopeKey] = importsRemaining
scopesWrapped[scopeKeyWrapped] = scopeValueWrapped
if (scopeKeyWrapped !== scopeKey) {
scopesWrapped[scopeKey] = { ...scopeValueWrapped }
}
})
return {
...scopesKeyWrapped,
...scopesRemaining,
}
return scopesWrapped
}

@@ -127,3 +119,3 @@

const wrapImports = (imports, into) => {
const importsWithKeyWrapped = {}
const importsWrapped = {}
const importsRemaining = {}

@@ -134,11 +126,10 @@

const importKeyWrapped = wrapSpecifier(importKey, into)
const importValueWrapped = wrapSpecifier(importValue, into)
const importValueWrapped = wrapAddress(importValue, into)
if (importKeyWrapped === importKey) {
const keyChanged = importKeyWrapped !== importKey
const valueChanged = importValueWrapped !== importValue
if (keyChanged || valueChanged) {
importsWrapped[importKeyWrapped] = importValueWrapped
} else {
importsRemaining[importKey] = importValue
} else if (importValueWrapped === importValue) {
importsWithKeyWrapped[importKeyWrapped] = importValue
} else {
importsWithKeyWrapped[importKeyWrapped] = importValueWrapped
importsRemaining[importKey] = importValueWrapped
}

@@ -148,3 +139,3 @@ })

return {
importsWithKeyWrapped,
importsWrapped,
importsRemaining,

@@ -155,5 +146,5 @@ }

const wrapTopLevelImports = (imports, into) => {
const { importsWithKeyWrapped, importsRemaining } = wrapImports(imports, into)
const { importsWrapped, importsRemaining } = wrapImports(imports, into)
return {
...importsWithKeyWrapped,
...importsWrapped,
...importsRemaining,

@@ -164,9 +155,46 @@ }

const wrapSpecifier = (specifier, into) => {
if (isOriginRelativeSpecifier(specifier)) {
if (specifier.startsWith("//")) {
return specifier
}
if (specifier[0] === "/") {
return `${into}${specifier.slice(1)}`
}
if (isBareSpecifier(specifier)) {
return `${into}${specifier}`
if (specifier.startsWith("./")) {
return `./${into}${specifier.slice(2)}`
}
return specifier
}
const wrapAddress = (string, into) => {
if (string.startsWith("//")) {
return string
}
if (string[0] === "/") {
return `${into}${string.slice(1)}`
}
if (string.startsWith("./")) {
return `./${into}${string.slice(2)}`
}
if (string.startsWith("../")) {
return string
}
if (hasScheme(string)) {
return string
}
// bare
return `${into}${string}`
}
const formulateFolderRelativeNameMustBeAString = ({
folderRelativeName,
}) => `folderRelativeName must be a string.
--- folder relative name ---
${folderRelativeName}`

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc