cleanup 1
This commit is contained in:
parent
71684968f4
commit
f15e392806
@ -1,83 +0,0 @@
|
|||||||
/**
|
|
||||||
* Resolves a module specifier against an import map
|
|
||||||
* @param {string} specifier - The module specifier to resolve (bare specifier or absolute URL)
|
|
||||||
* @param {Object} importMap - The import map object containing imports and scopes
|
|
||||||
* @param {string} baseURL - The base URL for context (especially for scopes)
|
|
||||||
* @returns {string} The resolved URL
|
|
||||||
*/
|
|
||||||
export default function resolveImportMap(specifier, importMap, baseURL) {
|
|
||||||
|
|
||||||
// Check for exact matches first (most common case for bare specifiers)
|
|
||||||
const lookup = importMap.imports[specifier];
|
|
||||||
if (lookup) { return lookup; }
|
|
||||||
|
|
||||||
const Scanner =(obj)=>
|
|
||||||
{
|
|
||||||
// Check for path prefix matches (longest first)
|
|
||||||
const keys = Object.keys(obj)
|
|
||||||
.filter(key => key.endsWith('/'))
|
|
||||||
.sort((a, b) => b.length - a.length);
|
|
||||||
for (const key of keys)
|
|
||||||
{
|
|
||||||
if (specifier.startsWith(key))
|
|
||||||
{
|
|
||||||
const remainder = specifier.slice(key.length);
|
|
||||||
return obj[key] + remainder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const scan = Scanner(importMap.imports);
|
|
||||||
if (scan) {return scan}
|
|
||||||
|
|
||||||
// Handle scopes if available
|
|
||||||
if (importMap.scopes) {
|
|
||||||
const scopeKeys = Object.keys(importMap.scopes).sort((a, b) => b.length - a.length);
|
|
||||||
for (const scopeKey of scopeKeys)
|
|
||||||
{
|
|
||||||
if (specifier.startsWith(scopeKey))
|
|
||||||
{
|
|
||||||
const scopeImports = importMap.scopes[scopeKey];
|
|
||||||
const scan = Scanner(scopeImports);
|
|
||||||
if (scan) {return scan}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return specifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Example usage for bare specifiers:
|
|
||||||
function demonstrateOptimizedResolver() {
|
|
||||||
const importMap = {
|
|
||||||
"imports": {
|
|
||||||
"lodash": "https://cdn.skypack.dev/lodash",
|
|
||||||
"react": "https://cdn.skypack.dev/react",
|
|
||||||
"lib/": "/node_modules/lib/",
|
|
||||||
"components/": "/components/"
|
|
||||||
},
|
|
||||||
"scopes": {
|
|
||||||
"/admin/": {
|
|
||||||
"components/": "/admin-components/",
|
|
||||||
"admin-utils": "scoped!/js/admin-utils.js"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Examples with bare specifiers
|
|
||||||
console.log("Resolving 'lodash':", resolveImportMap("lodash", importMap, "https://example.com/admin/dashboard/"));
|
|
||||||
console.log("Resolving 'components/button':", resolveImportMap("components/button", importMap, "https://example.com/admin/dashboard/"));
|
|
||||||
|
|
||||||
// Example with scope
|
|
||||||
console.log("Resolving 'admin-utils':",
|
|
||||||
resolveImportMap("admin-utils", importMap, "https://example.com/admin/dashboard/"));
|
|
||||||
|
|
||||||
console.log("Resolving '/admin/admin-utils':",
|
|
||||||
resolveImportMap("admin-utils", importMap, "https://example.com/admin/dashboard/"));
|
|
||||||
|
|
||||||
// Example with URL
|
|
||||||
console.log("Resolving 'https://example.com/external.js':",
|
|
||||||
resolveImportMap("https://example.com/external.js", importMap, "https://example.com/admin/dashboard/"));
|
|
||||||
}
|
|
||||||
|
|
||||||
demonstrateOptimizedResolver();
|
|
96
mod.ts
96
mod.ts
@ -1,8 +1,65 @@
|
|||||||
import * as ESBuild from "https://deno.land/x/esbuild@v0.25.0/wasm.js";
|
import * as ESBuild from "https://deno.land/x/esbuild@v0.25.0/wasm.js";
|
||||||
import * as Mapper from "https://esm.sh/esbuild-plugin-importmaps@1.0.0"; // https://github.com/andstellar/esbuild-plugin-importmaps
|
|
||||||
import Introspect from "./introspect.ts";
|
|
||||||
|
|
||||||
const resolvePlugin =(fullPathDir:string):ESBuild.Plugin=>({
|
/**
|
||||||
|
* Resolves a module specifier against an import map
|
||||||
|
* @param {string} specifier - The module specifier to resolve (bare specifier or absolute URL)
|
||||||
|
* @param {Object} importMap - The import map object containing imports and scopes
|
||||||
|
* @param {string} baseURL - The base URL for context (especially for scopes)
|
||||||
|
* @returns {string} The resolved URL
|
||||||
|
*/
|
||||||
|
function resolveImportMap(specifier, importMap, baseURL) {
|
||||||
|
|
||||||
|
// Check for prefix matches in the main imports
|
||||||
|
const result = checkPrefixMatch(specifier, importMap.imports);
|
||||||
|
if (result) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// First check scopes that match the baseURL (scope applies based on baseURL, not specifier)
|
||||||
|
if (importMap.scopes) {
|
||||||
|
const scopeKeys = Object.keys(importMap.scopes).sort((a, b) => b.length - a.length);
|
||||||
|
|
||||||
|
for (const scopeKey of scopeKeys) {
|
||||||
|
// Convert scope key to absolute URL and check if baseURL starts with it
|
||||||
|
const scopeURL = new URL(scopeKey, baseURL).href;
|
||||||
|
|
||||||
|
if (baseURL.startsWith(scopeURL)) {
|
||||||
|
const scopeImports = importMap.scopes[scopeKey];
|
||||||
|
|
||||||
|
// Check for prefix match in the scope
|
||||||
|
const result = checkPrefixMatch(specifier, scopeImports);
|
||||||
|
if (result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to check for prefix matches
|
||||||
|
* @param {string} specifier - The specifier to check
|
||||||
|
* @param {Object} mappings - Object with prefix mappings
|
||||||
|
* @returns {string|null} The resolved path or null if no match
|
||||||
|
*/
|
||||||
|
function checkPrefixMatch(specifier, mappings) {
|
||||||
|
|
||||||
|
const check = mappings[specifier];
|
||||||
|
if(check){ return check; }
|
||||||
|
|
||||||
|
const prefixes = Object.keys(mappings)
|
||||||
|
.filter(key => key.endsWith('/') && specifier.startsWith(key))
|
||||||
|
.sort((a, b) => b.length - a.length);
|
||||||
|
|
||||||
|
for (const prefix of prefixes) {
|
||||||
|
const remainder = specifier.slice(prefix.length);
|
||||||
|
return mappings[prefix] + remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolvePlugin =(fullPathDir:string, importMap):ESBuild.Plugin=>({
|
||||||
name: "resolve-plugin",
|
name: "resolve-plugin",
|
||||||
setup(build) {
|
setup(build) {
|
||||||
|
|
||||||
@ -16,11 +73,19 @@ const resolvePlugin =(fullPathDir:string):ESBuild.Plugin=>({
|
|||||||
return out;
|
return out;
|
||||||
} );
|
} );
|
||||||
|
|
||||||
build.onResolve( {/* `file://`, `http://`, and `https://` */ filter:/^(file:\/\/|http:\/\/|https:\/\/).*/}, args=>{
|
build.onResolve({filter:/.*/}, args=>{
|
||||||
const out = { path:args.path, namespace:"FULLPATH" };
|
|
||||||
console.log(`FULLPATH RESOLVE`, {args, out}, "\n");
|
const check = resolveImportMap(args.path, importMap, args.importer||fullPathDir);
|
||||||
return out;
|
console.log("pth??", check);
|
||||||
} );
|
if(check)
|
||||||
|
{
|
||||||
|
const resolveRoot = args.importer||fullPathDir;
|
||||||
|
const out = { path:new URL(check, resolveRoot).href, namespace:"FULLPATH" };
|
||||||
|
console.log(`IMPORTMAP RESOLVE`, {args, out}, "\n");
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
build.onLoad(
|
build.onLoad(
|
||||||
{/* `file://`, `http://`, and `https://` */ filter:/^(file:\/\/|http:\/\/|https:\/\/).*/},
|
{/* `file://`, `http://`, and `https://` */ filter:/^(file:\/\/|http:\/\/|https:\/\/).*/},
|
||||||
@ -35,22 +100,18 @@ const resolvePlugin =(fullPathDir:string):ESBuild.Plugin=>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
await ESBuild.initialize({ worker: false });
|
await ESBuild.initialize({ worker: false });
|
||||||
export type ImportMap = Parameters<typeof Mapper.importmapPlugin>[0];
|
export type ImportMap = {imports?:Record<string, string>, scopes?:Record<string, Record<string, string>>}
|
||||||
export type BuildOptions = ESBuild.BuildOptions;
|
export type BuildOptions = ESBuild.BuildOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {string} directory Full file:// or http(s):// path to the directory containing assets you want to build (needed to resolve relative imports)
|
* @param {string} directory Full file:// or http(s):// path to the directory containing assets you want to build (needed to resolve relative imports)
|
||||||
* @param {ESBuild.BuildOptions} buildOptions ESBuild "build" options (will be merged with "reasonable defaults") for docs: https://esbuild.github.io/api/#general-options
|
* @param {ESBuild.BuildOptions} [buildOptions={}] ESBuild "build" options (will be merged with "reasonable defaults") for docs: https://esbuild.github.io/api/#general-options
|
||||||
* @param {ImportMap|null} importMap An object to act as the import map ({imports:Record<string, string>}). If this is left blank, a configuration will be scanned for in the "directory"
|
* @param {ImportMap|null} [importMap={}] An object to act as the import map ({imports:Record<string, string>}). If this is left blank, a configuration will be scanned for in the "directory"
|
||||||
* @returns {Promise<ESBuild.BuildResult<ESBuild.BuildOptions>>} build result
|
* @returns {Promise<ESBuild.BuildResult<ESBuild.BuildOptions>>} build result
|
||||||
*/
|
*/
|
||||||
export default async function(directory, buildOptions={}, importMap)
|
export default async function Build(directory, buildOptions={}, importMap = {})
|
||||||
{
|
{
|
||||||
if(!importMap)
|
|
||||||
{
|
|
||||||
importMap = await Introspect(directory) as ImportMap
|
|
||||||
}
|
|
||||||
console.log("using import map", importMap);
|
console.log("using import map", importMap);
|
||||||
const configuration:ESBuild.BuildOptions = {
|
const configuration:ESBuild.BuildOptions = {
|
||||||
entryPoints: ["entry"],
|
entryPoints: ["entry"],
|
||||||
@ -61,8 +122,7 @@ export default async function(directory, buildOptions={}, importMap)
|
|||||||
jsxImportSource: "react",
|
jsxImportSource: "react",
|
||||||
...buildOptions,
|
...buildOptions,
|
||||||
plugins: [
|
plugins: [
|
||||||
Mapper.importmapPlugin(importMap) as ESBuild.Plugin,
|
resolvePlugin(directory, importMap),
|
||||||
resolvePlugin(directory),
|
|
||||||
...buildOptions.plugins||[]
|
...buildOptions.plugins||[]
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user