1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
|
package godartsass
import (
"fmt"
"path/filepath"
"strings"
"time"
"github.com/bep/godartsass/internal/embeddedsassv1"
)
// 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
// LogEventHandler will, if set, receive log events from Dart Sass,
// e.g. @debug and @warn log statements.
LogEventHandler func(LogEvent)
}
// LogEvent is a type of log event from Dart Sass.
type LogEventType int
const (
// Usually triggered by the @warn directive.
LogEventTypeWarning LogEventType = iota
// Events trigered for usage of deprecated Sass features.
LogEventTypeDeprecated
// Triggered by the @debug directive.
LogEventTypeDebug
)
type LogEvent struct {
// Type is the type of log event.
Type LogEventType
// Message on the form url:line:col message.
Message string
}
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) (Import, error)
}
type Import struct {
// The content of the imported file.
Content string
// The syntax of the imported file.
SourceSyntax SourceSyntax
}
// 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
// If enabled, sources will be embedded in the generated source map.
SourceMapIncludeSources 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 embeddedsassv1.OutputStyle
sassSourceSyntax embeddedsassv1.Syntax
// Ordered list starting with options.ImportResolver, then IncludePaths.
sassImporters []*embeddedsassv1.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 := embeddedsassv1.OutputStyle_value[string(args.OutputStyle)]
if !ok {
return fmt.Errorf("invalid OutputStyle %q", args.OutputStyle)
}
args.sassOutputStyle = embeddedsassv1.OutputStyle(v)
v, ok = embeddedsassv1.Syntax_value[string(args.SourceSyntax)]
if !ok {
return fmt.Errorf("invalid SourceSyntax %q", args.SourceSyntax)
}
args.sassSourceSyntax = embeddedsassv1.Syntax(v)
if args.ImportResolver != nil {
args.sassImporters = []*embeddedsassv1.InboundMessage_CompileRequest_Importer{
{
Importer: &embeddedsassv1.InboundMessage_CompileRequest_Importer_ImporterId{
ImporterId: seq,
},
},
}
}
if args.IncludePaths != nil {
for _, p := range args.IncludePaths {
args.sassImporters = append(args.sassImporters, &embeddedsassv1.InboundMessage_CompileRequest_Importer{Importer: &embeddedsassv1.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
}
}
|