-
Notifications
You must be signed in to change notification settings - Fork 55
Open
Labels
Description
Many modern websites now chained imports for their JavaScript.
It's time to parse JS like I used to parse CSS!
PoC:
package main
import (
_ "embed"
"fmt"
"strings"
"github.com/tdewolff/parse/v2"
"github.com/tdewolff/parse/v2/js"
)
var src string = `
// static import
import { slice } from "lodash";
import React from 'react';
// dynamic import
import('./a.js');
import("b.js").then(() => console.log('loaded'));
`
func extractImportStrings(ast *js.AST) []string {
var imports []string
js.Walk(&importVisitor{imports: &imports}, ast)
return imports
}
type importVisitor struct {
imports *[]string
}
func (v *importVisitor) Enter(n js.INode) js.IVisitor {
if call, ok := n.(*js.CallExpr); ok {
if lit, ok := call.X.(*js.LiteralExpr); ok && lit.TokenType == js.ImportToken {
if len(call.Args.List) > 0 {
if strLit, ok := call.Args.List[0].Value.(*js.LiteralExpr); ok && strLit.TokenType == js.StringToken {
*v.imports = append(*v.imports, strings.Trim(string(strLit.Data), `"'`))
}
}
}
}
if importStmt, ok := n.(*js.ImportStmt); ok {
*v.imports = append(*v.imports, strings.Trim(string(importStmt.Module), `"'`))
}
return v
}
func (v *importVisitor) Exit(n js.INode) {}
func main() {
input := parse.NewInput(strings.NewReader(src))
ast, err := js.Parse(input, js.Options{})
if err != nil {
panic(err)
}
importStrings := extractImportStrings(ast)
fmt.Println("Extracted import() strings:")
for _, s := range importStrings {
fmt.Println(s)
}
}stdout:
Extracted import() strings:
lodash
react
./a.js
b.js
Reactions are currently unavailable