193 lines
5.3 KiB
Go
193 lines
5.3 KiB
Go
package godartsass
|
|
|
|
import (
|
|
"fmt"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/bep/godartsass/internal/embeddedsass"
|
|
)
|
|
|
|
// Options configures a Transpiler.
|
|
type Options struct {
|
|
// The path to the Dart Sass wrapper binary, an absolute filename
|
|
// if not in $PATH.
|
|
// If this is not set, we will try 'dart-sass-embedded'
|
|
// (or 'dart-sass-embedded.bat' on Windows) in the OS $PATH.
|
|
// There may be several ways to install this, one would be to
|
|
// download it from here: https://github.com/sass/dart-sass-embedded/releases
|
|
DartSassEmbeddedFilename string
|
|
|
|
// Timeout is the duration allowed for dart sass to transpile.
|
|
// This was added for the beta6 version of Dart Sass Protocol,
|
|
// as running this code against the beta5 binary would hang
|
|
// on Execute.
|
|
Timeout time.Duration
|
|
}
|
|
|
|
func (opts *Options) init() error {
|
|
if opts.DartSassEmbeddedFilename == "" {
|
|
opts.DartSassEmbeddedFilename = defaultDartSassEmbeddedFilename
|
|
}
|
|
|
|
if opts.Timeout == 0 {
|
|
opts.Timeout = 30 * time.Second
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ImportResolver allows custom import resolution.
|
|
//
|
|
// CanonicalizeURL should create a canonical version of the given URL if it's
|
|
// able to resolve it, else return an empty string.
|
|
//
|
|
// A canonicalized URL should include a scheme, e.g. 'file:///foo/bar.scss',
|
|
// if applicable, see:
|
|
// https://en.wikipedia.org/wiki/File_URI_scheme
|
|
//
|
|
// Importers must ensure that the same canonical URL
|
|
// always refers to the same stylesheet.
|
|
//
|
|
// Load loads the canonicalized URL's content.
|
|
type ImportResolver interface {
|
|
CanonicalizeURL(url string) (string, error)
|
|
Load(canonicalizedURL string) (string, error)
|
|
}
|
|
|
|
// Args holds the arguments to Execute.
|
|
type Args struct {
|
|
// The input source.
|
|
Source string
|
|
|
|
// The URL of the Source.
|
|
// Leave empty if it's unknown.
|
|
// Must include a scheme, e.g. 'file:///myproject/main.scss'
|
|
// See https://en.wikipedia.org/wiki/File_URI_scheme
|
|
//
|
|
// Note: There is an open issue for this value when combined with custom
|
|
// importers, see https://github.com/sass/dart-sass-embedded/issues/24
|
|
URL string
|
|
|
|
// Defaults is SCSS.
|
|
SourceSyntax SourceSyntax
|
|
|
|
// Default is EXPANDED.
|
|
OutputStyle OutputStyle
|
|
|
|
// If enabled, a sourcemap will be generated and returned in Result.
|
|
EnableSourceMap bool
|
|
|
|
// Custom resolver to use to resolve imports.
|
|
// If set, this will be the first in the resolver chain.
|
|
ImportResolver ImportResolver
|
|
|
|
// Additional file paths to uses to resolve imports.
|
|
IncludePaths []string
|
|
|
|
sassOutputStyle embeddedsass.InboundMessage_CompileRequest_OutputStyle
|
|
sassSourceSyntax embeddedsass.InboundMessage_Syntax
|
|
|
|
// Ordered list starting with options.ImportResolver, then IncludePaths.
|
|
sassImporters []*embeddedsass.InboundMessage_CompileRequest_Importer
|
|
}
|
|
|
|
func (args *Args) init(seq uint32, opts Options) error {
|
|
if args.OutputStyle == "" {
|
|
args.OutputStyle = OutputStyleExpanded
|
|
}
|
|
if args.SourceSyntax == "" {
|
|
args.SourceSyntax = SourceSyntaxSCSS
|
|
}
|
|
|
|
v, ok := embeddedsass.InboundMessage_CompileRequest_OutputStyle_value[string(args.OutputStyle)]
|
|
if !ok {
|
|
return fmt.Errorf("invalid OutputStyle %q", args.OutputStyle)
|
|
}
|
|
args.sassOutputStyle = embeddedsass.InboundMessage_CompileRequest_OutputStyle(v)
|
|
|
|
v, ok = embeddedsass.InboundMessage_Syntax_value[string(args.SourceSyntax)]
|
|
if !ok {
|
|
return fmt.Errorf("invalid SourceSyntax %q", args.SourceSyntax)
|
|
}
|
|
|
|
args.sassSourceSyntax = embeddedsass.InboundMessage_Syntax(v)
|
|
|
|
if args.ImportResolver != nil {
|
|
args.sassImporters = []*embeddedsass.InboundMessage_CompileRequest_Importer{
|
|
{
|
|
Importer: &embeddedsass.InboundMessage_CompileRequest_Importer_ImporterId{
|
|
ImporterId: seq,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
if args.IncludePaths != nil {
|
|
for _, p := range args.IncludePaths {
|
|
args.sassImporters = append(args.sassImporters, &embeddedsass.InboundMessage_CompileRequest_Importer{Importer: &embeddedsass.InboundMessage_CompileRequest_Importer_Path{
|
|
Path: filepath.Clean(p),
|
|
}})
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type (
|
|
// OutputStyle defines the style of the generated CSS.
|
|
OutputStyle string
|
|
|
|
// SourceSyntax defines the syntax of the source passed in Execute.
|
|
SourceSyntax string
|
|
)
|
|
|
|
const (
|
|
// Expanded (default) output.
|
|
// Note that LibSASS and Ruby SASS have more output styles, and their
|
|
// default is NESTED.
|
|
OutputStyleExpanded OutputStyle = "EXPANDED"
|
|
|
|
// Compressed/minified output.
|
|
OutputStyleCompressed OutputStyle = "COMPRESSED"
|
|
)
|
|
|
|
const (
|
|
// SCSS style source syntax (default).
|
|
SourceSyntaxSCSS SourceSyntax = "SCSS"
|
|
|
|
// Indented or SASS style source syntax.
|
|
SourceSyntaxSASS SourceSyntax = "INDENTED"
|
|
|
|
// Regular CSS source syntax.
|
|
SourceSyntaxCSS SourceSyntax = "CSS"
|
|
)
|
|
|
|
// ParseOutputStyle will convert s into OutputStyle.
|
|
// Case insensitive, returns OutputStyleNested for unknown value.
|
|
func ParseOutputStyle(s string) OutputStyle {
|
|
switch OutputStyle(strings.ToUpper(s)) {
|
|
case OutputStyleCompressed:
|
|
return OutputStyleCompressed
|
|
case OutputStyleExpanded:
|
|
return OutputStyleExpanded
|
|
default:
|
|
return OutputStyleExpanded
|
|
}
|
|
}
|
|
|
|
// ParseSourceSyntax will convert s into SourceSyntax.
|
|
// Case insensitive, returns SourceSyntaxSCSS for unknown value.
|
|
func ParseSourceSyntax(s string) SourceSyntax {
|
|
switch SourceSyntax(strings.ToUpper(s)) {
|
|
case SourceSyntaxSCSS:
|
|
return SourceSyntaxSCSS
|
|
case SourceSyntaxSASS, "SASS":
|
|
return SourceSyntaxSASS
|
|
case SourceSyntaxCSS:
|
|
return SourceSyntaxCSS
|
|
default:
|
|
return SourceSyntaxSCSS
|
|
}
|
|
}
|