Skip to content
This repository was archived by the owner on Feb 10, 2020. It is now read-only.

Commit 7917cfb

Browse files
committed
Add OutputStyle conversion and some tests
1 parent dfacfaa commit 7917cfb

File tree

5 files changed

+157
-32
lines changed

5 files changed

+157
-32
lines changed

‎scss/common.go‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ package scss
1111
import (
1212
"encoding/json"
1313
"fmt"
14+
"strings"
1415
)
1516

1617
type (
@@ -24,6 +25,43 @@ const (
2425
CompressedStyle
2526
)
2627

28+
const (
29+
nestedStyleStr = "nested"
30+
expandedStyleStr = "expanded"
31+
compactStyleStr = "compact"
32+
compressedStyleStr = "compressed"
33+
)
34+
35+
var outputStyleFromString = map[string]OutputStyle{
36+
nestedStyleStr: NestedStyle,
37+
expandedStyleStr: ExpandedStyle,
38+
compactStyleStr: CompactStyle,
39+
compressedStyleStr: CompressedStyle,
40+
}
41+
42+
var outputStyleToString = map[OutputStyle]string{
43+
NestedStyle: nestedStyleStr,
44+
ExpandedStyle: expandedStyleStr,
45+
CompactStyle: compactStyleStr,
46+
CompressedStyle: compressedStyleStr,
47+
}
48+
49+
func OutputStyleFromString(style string) OutputStyle {
50+
os, found := outputStyleFromString[strings.ToLower(style)]
51+
if found {
52+
return os
53+
}
54+
return NestedStyle
55+
}
56+
57+
func OutputStyleToString(style OutputStyle) string {
58+
os, found := outputStyleToString[style]
59+
if found {
60+
return os
61+
}
62+
return nestedStyleStr
63+
}
64+
2765
type Options struct {
2866
// Default is nested.
2967
OutputStyle OutputStyle
@@ -41,6 +79,9 @@ type Options struct {
4179
// Source map settings
4280
SourceMapFilename string
4381
SourceMapRoot string
82+
InputPath string
83+
OutputPath string
84+
SourceMapContents bool
4485
OmitSourceMapURL bool
4586
EnableEmbeddedSourceMap bool
4687
}

‎scss/common_test.go‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright © 2018 Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>.
2+
//
3+
// Use of this source code is governed by an MIT-style
4+
// license that can be found in the LICENSE file.
5+
6+
// Package scss provides options for SCSS transpilers. Note that there are no
7+
// current pure Go SASS implementation, so the only option is CGO and LibSASS.
8+
// But hopefully, fingers crossed, this will happen.
9+
package scss
10+
11+
import (
12+
"testing"
13+
14+
"github.com/stretchr/testify/require"
15+
)
16+
17+
func TestOutputStyle(t *testing.T) {
18+
assert := require.New(t)
19+
assert.Equal(NestedStyle, OutputStyleFromString("nested"))
20+
assert.Equal(ExpandedStyle, OutputStyleFromString("expanded"))
21+
assert.Equal(CompactStyle, OutputStyleFromString("compact"))
22+
assert.Equal(CompressedStyle, OutputStyleFromString("compressed"))
23+
assert.Equal(NestedStyle, OutputStyleFromString("moo"))
24+
25+
assert.Equal("nested", OutputStyleToString(NestedStyle))
26+
assert.Equal("expanded", OutputStyleToString(ExpandedStyle))
27+
assert.Equal("compact", OutputStyleToString(CompactStyle))
28+
assert.Equal("compressed", OutputStyleToString(CompressedStyle))
29+
assert.Equal("nested", OutputStyleToString(43))
30+
}

‎scss/libsass/transpiler.go‎

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,36 +17,38 @@ import (
1717
"github.com/wellington/go-libsass/libs"
1818
)
1919

20-
var _ tocss.Transpiler = (*libsassTranspiler)(nil)
21-
2220
type libsassTranspiler struct {
2321
options scss.Options
2422
}
2523

26-
func New(options scss.Options) (*libsassTranspiler, error) {
24+
// New creates a new libsass transpiler configured with the given options.
25+
func New(options scss.Options) (tocss.Transpiler, error) {
2726
return &libsassTranspiler{options: options}, nil
2827
}
2928

30-
func (t *libsassTranspiler) Execute(dst io.Writer, src io.Reader) error {
31-
// TODO(bep) basepath
29+
// Execute transpiles the SCSS from src into dst. Note that you can import
30+
// older SASS (.sass) files, but the main entry (src) currently needs to be SCSS.
31+
func (t *libsassTranspiler) Execute(dst io.Writer, src io.Reader) (tocss.Result, error) {
32+
var result tocss.Result
3233

3334
b, err := ioutil.ReadAll(src)
3435
if err != nil {
35-
return err
36+
return result, err
3637
}
3738
sourceStr := string(b)
3839

3940
dataCtx := libs.SassMakeDataContext(sourceStr)
40-
opts := libs.SassDataContextGetOptions(dataCtx)
4141

42-
if t.options.ImportResolver != nil {
43-
idx := libs.BindImporter(opts, t.options.ImportResolver)
44-
defer libs.RemoveImporter(idx)
45-
}
42+
opts := libs.SassDataContextGetOptions(dataCtx)
4643

4744
{
48-
4945
// Set options
46+
47+
if t.options.ImportResolver != nil {
48+
idx := libs.BindImporter(opts, t.options.ImportResolver)
49+
defer libs.RemoveImporter(idx)
50+
}
51+
5052
if t.options.Precision != 0 {
5153
libs.SassOptionSetPrecision(opts, t.options.Precision)
5254
}
@@ -59,6 +61,14 @@ func (t *libsassTranspiler) Execute(dst io.Writer, src io.Reader) error {
5961
libs.SassOptionSetSourceMapRoot(opts, t.options.SourceMapRoot)
6062
}
6163

64+
if t.options.OutputPath != "" {
65+
libs.SassOptionSetOutputPath(opts, t.options.OutputPath)
66+
}
67+
if t.options.InputPath != "" {
68+
libs.SassOptionSetInputPath(opts, t.options.InputPath)
69+
}
70+
71+
libs.SassOptionSetSourceMapContents(opts, t.options.SourceMapContents)
6272
libs.SassOptionSetOmitSourceMapURL(opts, t.options.OmitSourceMapURL)
6373
libs.SassOptionSetSourceMapEmbed(opts, t.options.EnableEmbeddedSourceMap)
6474
libs.SassOptionSetIncludePath(opts, strings.Join(t.options.IncludePaths, string(os.PathListSeparator)))
@@ -73,18 +83,18 @@ func (t *libsassTranspiler) Execute(dst io.Writer, src io.Reader) error {
7383
libs.SassCompilerParse(compiler)
7484
libs.SassCompilerExecute(compiler)
7585

76-
libs.SassOptionSetSourceMapEmbed(opts, t.options.EnableEmbeddedSourceMap)
77-
libs.SassOptionSetSourceMapContents(opts, true)
78-
7986
defer libs.SassDeleteCompiler(compiler)
8087

81-
result := libs.SassContextGetOutputString(ctx)
88+
outputString := libs.SassContextGetOutputString(ctx)
8289

83-
io.WriteString(dst, result)
90+
io.WriteString(dst, outputString)
8491

8592
if status := libs.SassContextGetErrorStatus(ctx); status != 0 {
86-
return scss.JSONToError(libs.SassContextGetErrorJSON(ctx))
93+
return result, scss.JSONToError(libs.SassContextGetErrorJSON(ctx))
8794
}
8895

89-
return nil
96+
result.SourceMapFilename = libs.SassOptionGetSourceMapFile(opts)
97+
result.SourceMapContent = libs.SassContextGetSourceMapString(ctx)
98+
99+
return result, nil
90100
}

‎scss/libsass/transpiler_test.go‎

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ package libsass
77

88
import (
99
"bytes"
10+
"io/ioutil"
11+
"os"
12+
"path/filepath"
1013
"sync"
1114
"testing"
1215

@@ -33,7 +36,8 @@ div { p { color: $white; } }`)
3336
transpiler, err := New(scss.Options{ImportResolver: importResolver})
3437
assert.NoError(err)
3538

36-
assert.NoError(transpiler.Execute(&dst, src))
39+
_, err = transpiler.Execute(&dst, src)
40+
assert.NoError(err)
3741
assert.Equal("div p {\n color: #fff; }\n", dst.String())
3842
}
3943

@@ -47,10 +51,51 @@ div { p { color: #ccc; } }`)
4751
transpiler, err := New(scss.Options{OutputStyle: scss.CompressedStyle})
4852
assert.NoError(err)
4953

50-
assert.NoError(transpiler.Execute(&dst, src))
54+
_, err = transpiler.Execute(&dst, src)
55+
assert.NoError(err)
5156
assert.Equal("div p{color:#ccc}\n", dst.String())
5257
}
5358

59+
func TestSourceMapSettings(t *testing.T) {
60+
dir, _ := ioutil.TempDir(os.TempDir(), "tocss")
61+
defer os.RemoveAll(dir)
62+
63+
colors := filepath.Join(dir, "_colors.scss")
64+
65+
ioutil.WriteFile(colors, []byte(`
66+
$moo: #f442d1 !default;
67+
`), 0755)
68+
69+
assert := require.New(t)
70+
src := bytes.NewBufferString(`
71+
@import "colors";
72+
73+
div { p { color: $moo; } }`)
74+
75+
var dst bytes.Buffer
76+
77+
transpiler, err := New(scss.Options{
78+
IncludePaths: []string{dir},
79+
EnableEmbeddedSourceMap: false,
80+
SourceMapContents: true,
81+
OmitSourceMapURL: false,
82+
SourceMapFilename: "source.map",
83+
OutputPath: "outout.css",
84+
InputPath: "input.scss",
85+
SourceMapRoot: "/my/root",
86+
})
87+
assert.NoError(err)
88+
89+
result, err := transpiler.Execute(&dst, src)
90+
assert.NoError(err)
91+
assert.Equal("div p {\n color: #f442d1; }\n\n/*# sourceMappingURL=source.map */", dst.String())
92+
assert.Equal("source.map", result.SourceMapFilename)
93+
assert.Contains(result.SourceMapContent, `"sourceRoot": "/my/root",`)
94+
assert.Contains(result.SourceMapContent, `"file": "outout.css",`)
95+
assert.Contains(result.SourceMapContent, `"input.scss",`)
96+
assert.Contains(result.SourceMapContent, `mappings": "AAGA,AAAM,GAAH,CAAG,CAAC,CAAC;EAAE,KAAK,ECFH,OAAO,GDEM"`)
97+
}
98+
5499
func TestConcurrentTranspile(t *testing.T) {
55100

56101
assert := require.New(t)
@@ -77,7 +122,8 @@ func TestConcurrentTranspile(t *testing.T) {
77122
78123
div { p { color: $white; } }`)
79124
var dst bytes.Buffer
80-
assert.NoError(transpiler.Execute(&dst, src))
125+
_, err := transpiler.Execute(&dst, src)
126+
assert.NoError(err)
81127
assert.Equal("div p{color:#fff}\n", dst.String())
82128
}
83129
}()
@@ -101,19 +147,11 @@ func BenchmarkTranspile(b *testing.B) {
101147
src.Reset()
102148
dst.Reset()
103149
src.WriteString(srcs)
104-
if err := transpiler.Execute(&dst, &src); err != nil {
150+
if _, err := transpiler.Execute(&dst, &src); err != nil {
105151
b.Fatal(err)
106152
}
107153
if dst.String() != "div p{color:#ccc}\n" {
108154
b.Fatal("Got:", dst.String())
109155
}
110156
}
111157
}
112-
113-
// Options (tests)
114-
// SASS
115-
// SCSS
116-
// Preserve comments
117-
// Style (compressed?)
118-
// Basic benchmark
119-
// Multi threaded

‎tocss/transpiler.go‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ import (
1111
"io"
1212
)
1313

14+
type Result struct {
15+
// If source maps are configured.
16+
SourceMapFilename string
17+
SourceMapContent string
18+
}
19+
1420
type Transpiler interface {
15-
Execute(dst io.Writer, src io.Reader) error
21+
Execute(dst io.Writer, src io.Reader) (Result, error)
1622
}

0 commit comments

Comments
 (0)