Add support for import-maps
fuweichin opened this issue · 2 comments
Now all major browsers, as well as Node.js and Deno, support import-maps natively or with a custom loader. see
- https://caniuse.com/import-maps
- https://www.npmjs.com/package/@node-loader/import-maps
- https://deno.land/manual@v1.31.1/basics/import_maps
Some third party libs, e.g. xpath-analyzer, have used bare module specifiers, to use these libs in ClearScript runtime, currently I need to modify source code, transforming bare module specifiers into relative paths.
Hi @fuweichin,
ClearScript also supports custom loaders. You shouldn't have to modify any source code.
Let's walk through a simple example. Suppose you've installed xpath-analyzer as follows:
> npm install -g xpath-analyzer
Here are the relevant paths (on Windows):
var npmGlobalPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "npm");
var xpathAnalyzerPath = Path.Combine(npmGlobalPath, "node_modules", "xpath-analyzer");
var xpathLexerPath = Path.Combine(xpathAnalyzerPath, "node_modules", "xpath-lexer");
And here's a custom loader that supports simple mappings:
public class LoaderWithMap : DefaultDocumentLoader {
private readonly IReadOnlyDictionary<string, string> _map;
public LoaderWithMap(IDictionary<string, string> map) => _map = new ReadOnlyDictionary<string, string>(map);
public override Task<Document> LoadDocumentAsync(DocumentSettings settings, DocumentInfo? sourceInfo, string specifier, DocumentCategory category, DocumentContextCallback contextCallback) {
if (_map.TryGetValue(specifier, out var replacement)) specifier = replacement;
return base.LoadDocumentAsync(settings, sourceInfo, specifier, category, contextCallback);
}
}
You're now ready to set up the script engine:
using var engine = new V8ScriptEngine();
engine.DocumentSettings.AccessFlags = DocumentAccessFlags.EnableFileLoading;
engine.DocumentSettings.Loader = new LoaderWithMap(new Dictionary<string, string> {
{ "xpath-analyzer", Path.Combine(xpathAnalyzerPath, "dist", "xpath_analyzer.esm.js") },
{ "xpath-lexer", Path.Combine(xpathLexerPath, "dist", "xpath_lexer.esm.js") }
});
And run a test script:
engine.AddHostType(typeof(Console));
engine.Execute(new DocumentInfo { Category = ModuleCategory.Standard }, @"
import XPathAnalyzer from 'xpath-analyzer';
const analyzer = new XPathAnalyzer('123 + 456');
Console.WriteLine(JSON.stringify(analyzer.parse(), undefined, 2));
");
The output looks as expected:
{
"type": "additive",
"lhs": {
"type": "number",
"number": 123
},
"rhs": {
"type": "number",
"number": 456
}
}
Please let us know if this approach works for you.
Good luck!
It works.
Thank you!
B.T.W. It would be better to add an example about import-maps to FAQ Tutorial.