github.com/evanw/esbuild@v0.21.4/internal/css_parser/css_decls_composes.go (about) 1 package css_parser 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/evanw/esbuild/internal/ast" 8 "github.com/evanw/esbuild/internal/css_ast" 9 "github.com/evanw/esbuild/internal/css_lexer" 10 "github.com/evanw/esbuild/internal/logger" 11 ) 12 13 type composesContext struct { 14 parentRefs []ast.Ref 15 parentRange logger.Range 16 problemRange logger.Range 17 } 18 19 func (p *parser) handleComposesPragma(context composesContext, tokens []css_ast.Token) { 20 type nameWithLoc struct { 21 loc logger.Loc 22 text string 23 } 24 var names []nameWithLoc 25 fromGlobal := false 26 27 for i, t := range tokens { 28 if t.Kind == css_lexer.TIdent { 29 // Check for a "from" clause at the end 30 if strings.EqualFold(t.Text, "from") && i+2 == len(tokens) { 31 last := tokens[i+1] 32 33 // A string or a URL is an external file 34 if last.Kind == css_lexer.TString || last.Kind == css_lexer.TURL { 35 var importRecordIndex uint32 36 if last.Kind == css_lexer.TString { 37 importRecordIndex = uint32(len(p.importRecords)) 38 p.importRecords = append(p.importRecords, ast.ImportRecord{ 39 Kind: ast.ImportComposesFrom, 40 Path: logger.Path{Text: last.Text}, 41 Range: p.source.RangeOfString(last.Loc), 42 }) 43 } else { 44 importRecordIndex = last.PayloadIndex 45 p.importRecords[importRecordIndex].Kind = ast.ImportComposesFrom 46 } 47 for _, parentRef := range context.parentRefs { 48 composes := p.composes[parentRef] 49 for _, name := range names { 50 composes.ImportedNames = append(composes.ImportedNames, css_ast.ImportedComposesName{ 51 ImportRecordIndex: importRecordIndex, 52 Alias: name.text, 53 AliasLoc: name.loc, 54 }) 55 } 56 } 57 return 58 } 59 60 // An identifier must be "global" 61 if last.Kind == css_lexer.TIdent { 62 if strings.EqualFold(last.Text, "global") { 63 fromGlobal = true 64 break 65 } 66 67 p.log.AddID(logger.MsgID_CSS_CSSSyntaxError, logger.Warning, &p.tracker, css_lexer.RangeOfIdentifier(p.source, last.Loc), 68 fmt.Sprintf("\"composes\" declaration uses invalid location %q", last.Text)) 69 p.prevError = t.Loc 70 return 71 } 72 } 73 74 names = append(names, nameWithLoc{t.Loc, t.Text}) 75 continue 76 } 77 78 // Any unexpected tokens are a syntax error 79 var text string 80 switch t.Kind { 81 case css_lexer.TURL, css_lexer.TBadURL, css_lexer.TString, css_lexer.TUnterminatedString: 82 text = fmt.Sprintf("Unexpected %s", t.Kind.String()) 83 default: 84 text = fmt.Sprintf("Unexpected %q", t.Text) 85 } 86 p.log.AddID(logger.MsgID_CSS_CSSSyntaxError, logger.Warning, &p.tracker, logger.Range{Loc: t.Loc}, text) 87 p.prevError = t.Loc 88 return 89 } 90 91 // If we get here, all of these names are not references to another file 92 old := p.makeLocalSymbols 93 if fromGlobal { 94 p.makeLocalSymbols = false 95 } 96 for _, parentRef := range context.parentRefs { 97 composes := p.composes[parentRef] 98 for _, name := range names { 99 composes.Names = append(composes.Names, p.symbolForName(name.loc, name.text)) 100 } 101 } 102 p.makeLocalSymbols = old 103 }