Use vendored modules
Signed-off-by: Izuru Yakumo <yakumo.izuru@chaotic.ninja> git-svn-id: file:///srv/svn/repo/aya/trunk@67 cec141ff-132a-4243-88a5-ce187bd62f94
This commit is contained in:
27
vendor/github.com/yosssi/gcss/.gitignore
generated
vendored
Normal file
27
vendor/github.com/yosssi/gcss/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
|
||||
test/*.css
|
||||
cmd/gcss/test/*.css
|
||||
test/e2e/actual/*.css
|
||||
21
vendor/github.com/yosssi/gcss/LICENSE
generated
vendored
Normal file
21
vendor/github.com/yosssi/gcss/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Keiji Yoshida
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
2
vendor/github.com/yosssi/gcss/Makefile
generated
vendored
Normal file
2
vendor/github.com/yosssi/gcss/Makefile
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
t:
|
||||
@go test -cover -race ./...
|
||||
110
vendor/github.com/yosssi/gcss/README.md
generated
vendored
Normal file
110
vendor/github.com/yosssi/gcss/README.md
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
# GCSS - Pure Go CSS Preprocessor
|
||||
|
||||
[](https://app.wercker.com/project/bykey/4857161fd705e6c43df492e6a33ce87f)
|
||||
[](https://ci.appveyor.com/project/yosssi/gcss/branch/master)
|
||||
[](https://coveralls.io/r/yosssi/gcss?branch=master)
|
||||
[](http://godoc.org/github.com/yosssi/gcss)
|
||||
[](https://gitter.im/yosssi/gcss?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
|
||||
## Overview
|
||||
|
||||
GCSS is a pure Go CSS preprocessor. This is inspired by [Sass](http://sass-lang.com/) and [Stylus](http://learnboost.github.io/stylus/).
|
||||
|
||||
## Syntax
|
||||
|
||||
### Variables
|
||||
|
||||
```scss
|
||||
$base-font: Helvetica, sans-serif
|
||||
$main-color: blue
|
||||
|
||||
body
|
||||
font: 100% $base-font
|
||||
color: $main-color
|
||||
```
|
||||
|
||||
### Nesting
|
||||
|
||||
```scss
|
||||
nav
|
||||
ul
|
||||
margin: 0
|
||||
padding: 0
|
||||
|
||||
a
|
||||
color: blue
|
||||
&:hover
|
||||
color: red
|
||||
```
|
||||
|
||||
### Mixins
|
||||
|
||||
```scss
|
||||
$border-radius($radius)
|
||||
-webkit-border-radius: $radius
|
||||
-moz-border-radius: $radius
|
||||
-ms-border-radius: $radius
|
||||
border-radius: $radius
|
||||
|
||||
.box
|
||||
$border-radius(10px)
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
$ go get -u github.com/yosssi/gcss/...
|
||||
```
|
||||
|
||||
## Compile from the Command-Line
|
||||
|
||||
```sh
|
||||
$ gcss /path/to/gcss/file
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
$ cat /path/to/gcss/file | gcss > /path/to/css/file
|
||||
```
|
||||
|
||||
## Compile from Go programs
|
||||
|
||||
You can compile a GCSS file from Go programs by invoking the `gcss.CompileFile` function.
|
||||
|
||||
```go
|
||||
cssPath, err := gcss.CompileFile("path_to_gcss_file")
|
||||
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.ServeFile(w, r, cssPath)
|
||||
```
|
||||
|
||||
You can invoke the `gcss.Compile` function instead of the `gcss.CompileFile` function. The `gcss.Compile` function takes `io.Writer` and `io.Reader` as a parameter, compiles the GCSS data which is read from the `io.Reader` and writes the result CSS data to the `io.Writer`. Please see the [GoDoc](http://godoc.org/github.com/yosssi/gcss) for the details.
|
||||
|
||||
```go
|
||||
f, err := os.Open("path_to_gcss_file")
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := f.Close(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
n, err := gcss.Compile(os.Stdout, f)
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
* [GoDoc](http://godoc.org/github.com/yosssi/gcss)
|
||||
|
||||
## Syntax Highlightings
|
||||
|
||||
* [vim-gcss](https://github.com/yosssi/vim-gcss) - Vim syntax highlighting for GCSS
|
||||
59
vendor/github.com/yosssi/gcss/at_rule.go
generated
vendored
Normal file
59
vendor/github.com/yosssi/gcss/at_rule.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
package gcss
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// atRule represents an at-rule of CSS.
|
||||
type atRule struct {
|
||||
elementBase
|
||||
}
|
||||
|
||||
// WriteTo writes the at-rule to the writer.
|
||||
func (ar *atRule) WriteTo(w io.Writer) (int64, error) {
|
||||
bf := new(bytes.Buffer)
|
||||
|
||||
bf.WriteString(strings.TrimSpace(ar.ln.s))
|
||||
|
||||
if len(ar.sels) == 0 && len(ar.decs) == 0 && !ar.hasMixinDecs() && !ar.hasMixinSels() {
|
||||
bf.WriteString(semicolon)
|
||||
n, err := w.Write(bf.Bytes())
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
bf.WriteString(openBrace)
|
||||
|
||||
// Writing to the bytes.Buffer never returns an error.
|
||||
ar.writeDecsTo(bf, nil)
|
||||
|
||||
for _, sel := range ar.sels {
|
||||
// Writing to the bytes.Buffer never returns an error.
|
||||
sel.WriteTo(bf)
|
||||
}
|
||||
|
||||
// Write the mixin's selectors.
|
||||
for _, mi := range ar.mixins {
|
||||
sels, prms := mi.selsParams()
|
||||
|
||||
for _, sl := range sels {
|
||||
sl.parent = ar
|
||||
// Writing to the bytes.Buffer never returns an error.
|
||||
sl.writeTo(bf, prms)
|
||||
}
|
||||
}
|
||||
|
||||
bf.WriteString(closeBrace)
|
||||
|
||||
n, err := w.Write(bf.Bytes())
|
||||
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
// newAtRule creates and returns a at-rule.
|
||||
func newAtRule(ln *line, parent element) *atRule {
|
||||
return &atRule{
|
||||
elementBase: newElementBase(ln, parent),
|
||||
}
|
||||
}
|
||||
20
vendor/github.com/yosssi/gcss/comment.go
generated
vendored
Normal file
20
vendor/github.com/yosssi/gcss/comment.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
package gcss
|
||||
|
||||
import "io"
|
||||
|
||||
// comment represents a comment of CSS.
|
||||
type comment struct {
|
||||
elementBase
|
||||
}
|
||||
|
||||
// WriteTo does nothing.
|
||||
func (c *comment) WriteTo(w io.Writer) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// newComment creates and returns a comment.
|
||||
func newComment(ln *line, parent element) *comment {
|
||||
return &comment{
|
||||
elementBase: newElementBase(ln, parent),
|
||||
}
|
||||
}
|
||||
130
vendor/github.com/yosssi/gcss/compile.go
generated
vendored
Normal file
130
vendor/github.com/yosssi/gcss/compile.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
package gcss
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// extensions
|
||||
const (
|
||||
extCSS = ".css"
|
||||
extGCSS = ".gcss"
|
||||
)
|
||||
|
||||
// cssFilePath converts path's extenstion into a CSS file extension.
|
||||
var cssFilePath = func(path string) string {
|
||||
return convertExt(path, extCSS)
|
||||
}
|
||||
|
||||
// Compile compiles GCSS data which is read from src and
|
||||
// Writes the result CSS data to the dst.
|
||||
func Compile(dst io.Writer, src io.Reader) (int, error) {
|
||||
data, err := ioutil.ReadAll(src)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
bc, berrc := compileBytes(data)
|
||||
|
||||
bf := new(bytes.Buffer)
|
||||
|
||||
BufWriteLoop:
|
||||
for {
|
||||
select {
|
||||
case b, ok := <-bc:
|
||||
if !ok {
|
||||
break BufWriteLoop
|
||||
}
|
||||
|
||||
bf.Write(b)
|
||||
case err := <-berrc:
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
return dst.Write(bf.Bytes())
|
||||
}
|
||||
|
||||
// CompileFile parses the GCSS file specified by the path parameter,
|
||||
// generates a CSS file and returns the path of the generated CSS file
|
||||
// and an error when it occurs.
|
||||
func CompileFile(path string) (string, error) {
|
||||
data, err := ioutil.ReadFile(path)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
cssPath := cssFilePath(path)
|
||||
|
||||
bc, berrc := compileBytes(data)
|
||||
|
||||
done, werrc := write(cssPath, bc, berrc)
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
case err := <-werrc:
|
||||
return "", err
|
||||
}
|
||||
|
||||
return cssPath, nil
|
||||
}
|
||||
|
||||
// compileBytes parses the GCSS byte array passed as the s parameter,
|
||||
// generates a CSS byte array and returns the two channels: the first
|
||||
// one returns the CSS byte array and the last one returns an error
|
||||
// when it occurs.
|
||||
func compileBytes(b []byte) (<-chan []byte, <-chan error) {
|
||||
lines := strings.Split(formatLF(string(b)), lf)
|
||||
|
||||
bc := make(chan []byte, len(lines))
|
||||
errc := make(chan error)
|
||||
|
||||
go func() {
|
||||
ctx := newContext()
|
||||
|
||||
elemc, pErrc := parse(lines)
|
||||
|
||||
for {
|
||||
select {
|
||||
case elem, ok := <-elemc:
|
||||
if !ok {
|
||||
close(bc)
|
||||
return
|
||||
}
|
||||
|
||||
elem.SetContext(ctx)
|
||||
|
||||
switch v := elem.(type) {
|
||||
case *mixinDeclaration:
|
||||
ctx.mixins[v.name] = v
|
||||
case *variable:
|
||||
ctx.vars[v.name] = v
|
||||
case *atRule, *declaration, *selector:
|
||||
bf := new(bytes.Buffer)
|
||||
elem.WriteTo(bf)
|
||||
bc <- bf.Bytes()
|
||||
}
|
||||
case err := <-pErrc:
|
||||
errc <- err
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return bc, errc
|
||||
}
|
||||
|
||||
// Path converts path's extenstion into a GCSS file extension.
|
||||
func Path(path string) string {
|
||||
return convertExt(path, extGCSS)
|
||||
}
|
||||
|
||||
// convertExt converts path's extension into ext.
|
||||
func convertExt(path string, ext string) string {
|
||||
return strings.TrimSuffix(path, filepath.Ext(path)) + ext
|
||||
}
|
||||
15
vendor/github.com/yosssi/gcss/context.go
generated
vendored
Normal file
15
vendor/github.com/yosssi/gcss/context.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
package gcss
|
||||
|
||||
// context represents a context of the parsing process.
|
||||
type context struct {
|
||||
vars map[string]*variable
|
||||
mixins map[string]*mixinDeclaration
|
||||
}
|
||||
|
||||
// newContext creates and returns a context.
|
||||
func newContext() *context {
|
||||
return &context{
|
||||
vars: make(map[string]*variable),
|
||||
mixins: make(map[string]*mixinDeclaration),
|
||||
}
|
||||
}
|
||||
109
vendor/github.com/yosssi/gcss/declaration.go
generated
vendored
Normal file
109
vendor/github.com/yosssi/gcss/declaration.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
package gcss
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// declaration represents a declaration of CSS.
|
||||
type declaration struct {
|
||||
elementBase
|
||||
property string
|
||||
value string
|
||||
}
|
||||
|
||||
// WriteTo writes the declaration to the writer.
|
||||
func (dec *declaration) WriteTo(w io.Writer) (int64, error) {
|
||||
return dec.writeTo(w, nil)
|
||||
}
|
||||
|
||||
// writeTo writes the declaration to the writer.
|
||||
func (dec *declaration) writeTo(w io.Writer, params map[string]string) (int64, error) {
|
||||
bf := new(bytes.Buffer)
|
||||
|
||||
bf.WriteString(dec.property)
|
||||
bf.WriteString(colon)
|
||||
|
||||
for i, v := range strings.Split(dec.value, space) {
|
||||
if i > 0 {
|
||||
bf.WriteString(space)
|
||||
}
|
||||
|
||||
for j, w := range strings.Split(v, comma) {
|
||||
if j > 0 {
|
||||
bf.WriteString(comma)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(w, dollarMark) {
|
||||
// Writing to the bytes.Buffer never returns an error.
|
||||
dec.writeParamTo(bf, strings.TrimPrefix(w, dollarMark), params)
|
||||
} else {
|
||||
bf.WriteString(w)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bf.WriteString(semicolon)
|
||||
|
||||
n, err := w.Write(bf.Bytes())
|
||||
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
// writeParam writes the param to the writer.
|
||||
func (dec *declaration) writeParamTo(w io.Writer, name string, params map[string]string) (int64, error) {
|
||||
if s, ok := params[name]; ok {
|
||||
if strings.HasPrefix(s, dollarMark) {
|
||||
if v, ok := dec.Context().vars[strings.TrimPrefix(s, dollarMark)]; ok {
|
||||
return v.WriteTo(w)
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
n, err := w.Write([]byte(s))
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
if v, ok := dec.Context().vars[name]; ok {
|
||||
return v.WriteTo(w)
|
||||
}
|
||||
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// declarationPV extracts a declaration property and value
|
||||
// from the line.
|
||||
func declarationPV(ln *line) (string, string, error) {
|
||||
pv := strings.SplitN(strings.TrimSpace(ln.s), space, 2)
|
||||
|
||||
if len(pv) < 2 {
|
||||
return "", "", fmt.Errorf("declaration's property and value should be divided by a space [line: %d]", ln.no)
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(pv[0], colon) {
|
||||
return "", "", fmt.Errorf("property should end with a colon [line: %d]", ln.no)
|
||||
}
|
||||
|
||||
return strings.TrimSuffix(pv[0], colon), pv[1], nil
|
||||
}
|
||||
|
||||
// newDeclaration creates and returns a declaration.
|
||||
func newDeclaration(ln *line, parent element) (*declaration, error) {
|
||||
property, value, err := declarationPV(ln)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if strings.HasSuffix(value, semicolon) {
|
||||
return nil, fmt.Errorf("declaration must not end with %q [line: %d]", semicolon, ln.no)
|
||||
}
|
||||
|
||||
return &declaration{
|
||||
elementBase: newElementBase(ln, parent),
|
||||
property: property,
|
||||
value: value,
|
||||
}, nil
|
||||
}
|
||||
2
vendor/github.com/yosssi/gcss/doc.go
generated
vendored
Normal file
2
vendor/github.com/yosssi/gcss/doc.go
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package gcss provides the CSS preprocessor.
|
||||
package gcss
|
||||
41
vendor/github.com/yosssi/gcss/element.go
generated
vendored
Normal file
41
vendor/github.com/yosssi/gcss/element.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
package gcss
|
||||
|
||||
import "io"
|
||||
|
||||
// element represents an element of GCSS source codes.
|
||||
type element interface {
|
||||
io.WriterTo
|
||||
AppendChild(child element)
|
||||
Base() *elementBase
|
||||
SetContext(*context)
|
||||
Context() *context
|
||||
}
|
||||
|
||||
// newElement creates and returns an element.
|
||||
func newElement(ln *line, parent element) (element, error) {
|
||||
var e element
|
||||
var err error
|
||||
|
||||
switch {
|
||||
case ln.isComment():
|
||||
e = newComment(ln, parent)
|
||||
case ln.isAtRule():
|
||||
e = newAtRule(ln, parent)
|
||||
case ln.isMixinDeclaration():
|
||||
// error can be ignored becuase the line is checked beforehand
|
||||
// by calling `ln.isMixinDeclaration()`.
|
||||
e, _ = newMixinDeclaration(ln, parent)
|
||||
case ln.isMixinInvocation():
|
||||
// error can be ignored becuase the line is checked beforehand
|
||||
// by calling `ln.isMixinInvocation()`.
|
||||
e, _ = newMixinInvocation(ln, parent)
|
||||
case ln.isVariable():
|
||||
e, err = newVariable(ln, parent)
|
||||
case ln.isDeclaration():
|
||||
e, err = newDeclaration(ln, parent)
|
||||
default:
|
||||
e, err = newSelector(ln, parent)
|
||||
}
|
||||
|
||||
return e, err
|
||||
}
|
||||
104
vendor/github.com/yosssi/gcss/element_base.go
generated
vendored
Normal file
104
vendor/github.com/yosssi/gcss/element_base.go
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
package gcss
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
// elementBase holds the common fields of an element.
|
||||
type elementBase struct {
|
||||
ln *line
|
||||
parent element
|
||||
sels []*selector
|
||||
decs []*declaration
|
||||
mixins []*mixinInvocation
|
||||
ctx *context
|
||||
}
|
||||
|
||||
// AppendChild appends a child element to the element.
|
||||
func (eBase *elementBase) AppendChild(child element) {
|
||||
switch c := child.(type) {
|
||||
case *mixinInvocation:
|
||||
eBase.mixins = append(eBase.mixins, c)
|
||||
case *declaration:
|
||||
eBase.decs = append(eBase.decs, c)
|
||||
case *selector:
|
||||
eBase.sels = append(eBase.sels, c)
|
||||
}
|
||||
}
|
||||
|
||||
// Base returns the element base.
|
||||
func (eBase *elementBase) Base() *elementBase {
|
||||
return eBase
|
||||
}
|
||||
|
||||
// SetContext sets the context to the element.
|
||||
func (eBase *elementBase) SetContext(ctx *context) {
|
||||
eBase.ctx = ctx
|
||||
}
|
||||
|
||||
// Context returns the top element's context.
|
||||
func (eBase *elementBase) Context() *context {
|
||||
if eBase.parent != nil {
|
||||
return eBase.parent.Context()
|
||||
}
|
||||
|
||||
return eBase.ctx
|
||||
}
|
||||
|
||||
// hasMixinDecs returns true if the element has a mixin
|
||||
// which has declarations.
|
||||
func (eBase *elementBase) hasMixinDecs() bool {
|
||||
for _, mi := range eBase.mixins {
|
||||
if decs, _ := mi.decsParams(); len(decs) > 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// hasMixinSels returns true if the element has a mixin
|
||||
// which has selectors.
|
||||
func (eBase *elementBase) hasMixinSels() bool {
|
||||
for _, mi := range eBase.mixins {
|
||||
if sels, _ := mi.selsParams(); len(sels) > 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// writeDecsTo writes the element's declarations to w.
|
||||
func (eBase *elementBase) writeDecsTo(w io.Writer, params map[string]string) (int64, error) {
|
||||
bf := new(bytes.Buffer)
|
||||
|
||||
// Write the declarations.
|
||||
for _, dec := range eBase.decs {
|
||||
// Writing to the bytes.Buffer never returns an error.
|
||||
dec.writeTo(bf, params)
|
||||
}
|
||||
|
||||
// Write the mixin's declarations.
|
||||
for _, mi := range eBase.mixins {
|
||||
decs, prms := mi.decsParams()
|
||||
|
||||
for _, dec := range decs {
|
||||
// Writing to the bytes.Buffer never returns an error.
|
||||
dec.writeTo(bf, prms)
|
||||
}
|
||||
}
|
||||
|
||||
n, err := w.Write(bf.Bytes())
|
||||
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
// newElementBase creates and returns an element base.
|
||||
func newElementBase(ln *line, parent element) elementBase {
|
||||
return elementBase{
|
||||
ln: ln,
|
||||
parent: parent,
|
||||
}
|
||||
}
|
||||
114
vendor/github.com/yosssi/gcss/line.go
generated
vendored
Normal file
114
vendor/github.com/yosssi/gcss/line.go
generated
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
package gcss
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const unicodeSpace = 32
|
||||
|
||||
const indentTop = 0
|
||||
|
||||
// line represents a line of codes.
|
||||
type line struct {
|
||||
no int
|
||||
s string
|
||||
indent int
|
||||
}
|
||||
|
||||
// isEmpty returns true if the line's s is zero value.
|
||||
func (ln *line) isEmpty() bool {
|
||||
return strings.TrimSpace(ln.s) == ""
|
||||
}
|
||||
|
||||
// isTopIndent returns true if the line's indent is the top level.
|
||||
func (ln *line) isTopIndent() bool {
|
||||
return ln.indent == indentTop
|
||||
}
|
||||
|
||||
// childOf returns true if the line is a child of the parent.
|
||||
func (ln *line) childOf(parent element) (bool, error) {
|
||||
var ok bool
|
||||
var err error
|
||||
|
||||
switch pIndent := parent.Base().ln.indent; {
|
||||
case ln.indent == pIndent+1:
|
||||
ok = true
|
||||
case ln.indent > pIndent+1:
|
||||
err = fmt.Errorf("indent is invalid [line: %d]", ln.no)
|
||||
}
|
||||
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// isDeclaration returns true if the line is a declaration.
|
||||
func (ln *line) isDeclaration() bool {
|
||||
_, _, err := declarationPV(ln)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// isAtRule returns true if the line is an at-rule.
|
||||
func (ln *line) isAtRule() bool {
|
||||
return strings.HasPrefix(strings.TrimSpace(ln.s), atMark)
|
||||
}
|
||||
|
||||
// isVariable returns true if the line is a variable.
|
||||
func (ln *line) isVariable() bool {
|
||||
if !ln.isTopIndent() {
|
||||
return false
|
||||
}
|
||||
|
||||
_, _, err := variableNV(ln)
|
||||
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// isMixinDeclaration returns true if the line is a mixin declaration.
|
||||
func (ln *line) isMixinDeclaration() bool {
|
||||
if !ln.isTopIndent() {
|
||||
return false
|
||||
}
|
||||
|
||||
_, _, err := mixinNP(ln, true)
|
||||
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// isMixinInvocation returns true if the line is a mixin invocation.
|
||||
func (ln *line) isMixinInvocation() bool {
|
||||
if ln.isTopIndent() {
|
||||
return false
|
||||
}
|
||||
|
||||
_, _, err := mixinNP(ln, false)
|
||||
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// isComment returns true if the line is a comment.
|
||||
func (ln *line) isComment() bool {
|
||||
return strings.HasPrefix(strings.TrimSpace(ln.s), doubleSlash)
|
||||
}
|
||||
|
||||
// newLine creates and returns a line.
|
||||
func newLine(no int, s string) *line {
|
||||
return &line{
|
||||
no: no,
|
||||
s: s,
|
||||
indent: indent(s),
|
||||
}
|
||||
}
|
||||
|
||||
// indent returns the string's indent.
|
||||
func indent(s string) int {
|
||||
var i int
|
||||
|
||||
for _, b := range s {
|
||||
if b != unicodeSpace {
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
return i / 2
|
||||
}
|
||||
85
vendor/github.com/yosssi/gcss/mixin_declaration.go
generated
vendored
Normal file
85
vendor/github.com/yosssi/gcss/mixin_declaration.go
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
package gcss
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// mixinDeclaration represents a mixin declaration.
|
||||
type mixinDeclaration struct {
|
||||
elementBase
|
||||
name string
|
||||
paramNames []string
|
||||
}
|
||||
|
||||
// WriteTo writes the selector to the writer.
|
||||
func (md *mixinDeclaration) WriteTo(w io.Writer) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// mixinNP extracts a mixin name and parameters from the line.
|
||||
func mixinNP(ln *line, isDeclaration bool) (string, []string, error) {
|
||||
s := strings.TrimSpace(ln.s)
|
||||
|
||||
if !strings.HasPrefix(s, dollarMark) {
|
||||
return "", nil, fmt.Errorf("mixin must start with %q [line: %d]", dollarMark, ln.no)
|
||||
}
|
||||
|
||||
s = strings.TrimPrefix(s, dollarMark)
|
||||
|
||||
np := strings.Split(s, openParenthesis)
|
||||
|
||||
if len(np) != 2 {
|
||||
return "", nil, fmt.Errorf("mixin's format is invalid [line: %d]", ln.no)
|
||||
}
|
||||
|
||||
paramsS := strings.TrimSpace(np[1])
|
||||
|
||||
if !strings.HasSuffix(paramsS, closeParenthesis) {
|
||||
return "", nil, fmt.Errorf("mixin must end with %q [line: %d]", closeParenthesis, ln.no)
|
||||
}
|
||||
|
||||
paramsS = strings.TrimSuffix(paramsS, closeParenthesis)
|
||||
|
||||
if strings.Index(paramsS, closeParenthesis) != -1 {
|
||||
return "", nil, fmt.Errorf("mixin's format is invalid [line: %d]", ln.no)
|
||||
}
|
||||
|
||||
var params []string
|
||||
|
||||
if paramsS != "" {
|
||||
params = strings.Split(paramsS, comma)
|
||||
}
|
||||
|
||||
for i, p := range params {
|
||||
p = strings.TrimSpace(p)
|
||||
|
||||
if isDeclaration {
|
||||
if !strings.HasPrefix(p, dollarMark) {
|
||||
return "", nil, fmt.Errorf("mixin's parameter must start with %q [line: %d]", dollarMark, ln.no)
|
||||
}
|
||||
|
||||
p = strings.TrimPrefix(p, dollarMark)
|
||||
}
|
||||
|
||||
params[i] = p
|
||||
}
|
||||
|
||||
return np[0], params, nil
|
||||
}
|
||||
|
||||
// newMixinDeclaration creates and returns a mixin declaration.
|
||||
func newMixinDeclaration(ln *line, parent element) (*mixinDeclaration, error) {
|
||||
name, paramNames, err := mixinNP(ln, true)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &mixinDeclaration{
|
||||
elementBase: newElementBase(ln, parent),
|
||||
name: name,
|
||||
paramNames: paramNames,
|
||||
}, nil
|
||||
}
|
||||
72
vendor/github.com/yosssi/gcss/mixin_invocation.go
generated
vendored
Normal file
72
vendor/github.com/yosssi/gcss/mixin_invocation.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
package gcss
|
||||
|
||||
import "io"
|
||||
|
||||
// mixinInvocation represents a mixin invocation.
|
||||
type mixinInvocation struct {
|
||||
elementBase
|
||||
name string
|
||||
paramValues []string
|
||||
}
|
||||
|
||||
// WriteTo writes the selector to the writer.
|
||||
func (mi *mixinInvocation) WriteTo(w io.Writer) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// decsParams returns the mixin's declarations and params.
|
||||
func (mi *mixinInvocation) decsParams() ([]*declaration, map[string]string) {
|
||||
md, ok := mi.Context().mixins[mi.name]
|
||||
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
params := make(map[string]string)
|
||||
|
||||
l := len(mi.paramValues)
|
||||
|
||||
for i, name := range md.paramNames {
|
||||
if i < l {
|
||||
params[name] = mi.paramValues[i]
|
||||
}
|
||||
}
|
||||
|
||||
return md.decs, params
|
||||
}
|
||||
|
||||
// selsParams returns the mixin's selectors and params.
|
||||
func (mi *mixinInvocation) selsParams() ([]*selector, map[string]string) {
|
||||
md, ok := mi.Context().mixins[mi.name]
|
||||
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
params := make(map[string]string)
|
||||
|
||||
l := len(mi.paramValues)
|
||||
|
||||
for i, name := range md.paramNames {
|
||||
if i < l {
|
||||
params[name] = mi.paramValues[i]
|
||||
}
|
||||
}
|
||||
|
||||
return md.sels, params
|
||||
}
|
||||
|
||||
// newMixinInvocation creates and returns a mixin invocation.
|
||||
func newMixinInvocation(ln *line, parent element) (*mixinInvocation, error) {
|
||||
name, paramValues, err := mixinNP(ln, false)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &mixinInvocation{
|
||||
elementBase: newElementBase(ln, parent),
|
||||
name: name,
|
||||
paramValues: paramValues,
|
||||
}, nil
|
||||
}
|
||||
115
vendor/github.com/yosssi/gcss/parse.go
generated
vendored
Normal file
115
vendor/github.com/yosssi/gcss/parse.go
generated
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
package gcss
|
||||
|
||||
import "strings"
|
||||
|
||||
// Special characters
|
||||
const (
|
||||
cr = "\r"
|
||||
lf = "\n"
|
||||
crlf = "\r\n"
|
||||
space = " "
|
||||
colon = ":"
|
||||
comma = ","
|
||||
openBrace = "{"
|
||||
closeBrace = "}"
|
||||
semicolon = ";"
|
||||
ampersand = "&"
|
||||
atMark = "@"
|
||||
dollarMark = "$"
|
||||
openParenthesis = "("
|
||||
closeParenthesis = ")"
|
||||
slash = "/"
|
||||
doubleSlash = slash + slash
|
||||
)
|
||||
|
||||
// parse parses the string, generates the elements
|
||||
// and returns the two channels: the first one returns
|
||||
// the generated elements and the last one returns
|
||||
// an error when it occurs.
|
||||
func parse(lines []string) (<-chan element, <-chan error) {
|
||||
elemc := make(chan element, len(lines))
|
||||
errc := make(chan error)
|
||||
|
||||
go func() {
|
||||
i := 0
|
||||
l := len(lines)
|
||||
|
||||
for i < l {
|
||||
// Fetch a line.
|
||||
ln := newLine(i+1, lines[i])
|
||||
i++
|
||||
|
||||
// Ignore the empty line.
|
||||
if ln.isEmpty() {
|
||||
continue
|
||||
}
|
||||
|
||||
if ln.isTopIndent() {
|
||||
elem, err := newElement(ln, nil)
|
||||
|
||||
if err != nil {
|
||||
errc <- err
|
||||
return
|
||||
}
|
||||
|
||||
if err := appendChildren(elem, lines, &i, l); err != nil {
|
||||
errc <- err
|
||||
return
|
||||
}
|
||||
|
||||
elemc <- elem
|
||||
}
|
||||
}
|
||||
|
||||
close(elemc)
|
||||
}()
|
||||
|
||||
return elemc, errc
|
||||
}
|
||||
|
||||
// appendChildren parses the lines and appends the child elements
|
||||
// to the parent element.
|
||||
func appendChildren(parent element, lines []string, i *int, l int) error {
|
||||
for *i < l {
|
||||
// Fetch a line.
|
||||
ln := newLine(*i+1, lines[*i])
|
||||
|
||||
// Ignore the empty line.
|
||||
if ln.isEmpty() {
|
||||
*i++
|
||||
return nil
|
||||
}
|
||||
|
||||
ok, err := ln.childOf(parent)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
child, err := newElement(ln, parent)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parent.AppendChild(child)
|
||||
|
||||
*i++
|
||||
|
||||
if err := appendChildren(child, lines, i, l); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// formatLF replaces the line feed codes with LF and
|
||||
// returns the result string.
|
||||
func formatLF(s string) string {
|
||||
return strings.Replace(strings.Replace(s, crlf, lf, -1), cr, lf, -1)
|
||||
}
|
||||
110
vendor/github.com/yosssi/gcss/selector.go
generated
vendored
Normal file
110
vendor/github.com/yosssi/gcss/selector.go
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
package gcss
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// selector represents a selector of CSS.
|
||||
type selector struct {
|
||||
elementBase
|
||||
name string
|
||||
}
|
||||
|
||||
// WriteTo writes the selector to the writer.
|
||||
func (sel *selector) WriteTo(w io.Writer) (int64, error) {
|
||||
return sel.writeTo(w, nil)
|
||||
}
|
||||
|
||||
// writeTo writes the selector to the writer.
|
||||
func (sel *selector) writeTo(w io.Writer, params map[string]string) (int64, error) {
|
||||
bf := new(bytes.Buffer)
|
||||
|
||||
// Write the declarations.
|
||||
if len(sel.decs) > 0 || sel.hasMixinDecs() {
|
||||
bf.WriteString(sel.names())
|
||||
bf.WriteString(openBrace)
|
||||
|
||||
// Writing to the bytes.Buffer never returns an error.
|
||||
sel.writeDecsTo(bf, params)
|
||||
|
||||
bf.WriteString(closeBrace)
|
||||
}
|
||||
|
||||
// Write the child selectors.
|
||||
for _, childSel := range sel.sels {
|
||||
// Writing to the bytes.Buffer never returns an error.
|
||||
childSel.writeTo(bf, params)
|
||||
}
|
||||
|
||||
// Write the mixin's selectors.
|
||||
for _, mi := range sel.mixins {
|
||||
sels, prms := mi.selsParams()
|
||||
|
||||
for _, sl := range sels {
|
||||
sl.parent = sel
|
||||
// Writing to the bytes.Buffer never returns an error.
|
||||
sl.writeTo(bf, prms)
|
||||
}
|
||||
}
|
||||
|
||||
n, err := w.Write(bf.Bytes())
|
||||
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
// names returns the selector names.
|
||||
func (sel *selector) names() string {
|
||||
bf := new(bytes.Buffer)
|
||||
|
||||
switch parent := sel.parent.(type) {
|
||||
case nil, *atRule:
|
||||
for _, name := range strings.Split(sel.name, comma) {
|
||||
if bf.Len() > 0 {
|
||||
bf.WriteString(comma)
|
||||
}
|
||||
|
||||
bf.WriteString(strings.TrimSpace(name))
|
||||
}
|
||||
case *selector:
|
||||
for _, parentS := range strings.Split(parent.names(), comma) {
|
||||
for _, s := range strings.Split(sel.name, comma) {
|
||||
if bf.Len() > 0 {
|
||||
bf.WriteString(comma)
|
||||
}
|
||||
|
||||
s = strings.TrimSpace(s)
|
||||
|
||||
if strings.Index(s, ampersand) != -1 {
|
||||
bf.WriteString(strings.Replace(s, ampersand, parentS, -1))
|
||||
} else {
|
||||
bf.WriteString(parentS)
|
||||
bf.WriteString(space)
|
||||
bf.WriteString(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bf.String()
|
||||
}
|
||||
|
||||
// newSelector creates and returns a selector.
|
||||
func newSelector(ln *line, parent element) (*selector, error) {
|
||||
name := strings.TrimSpace(ln.s)
|
||||
|
||||
if strings.HasSuffix(name, openBrace) {
|
||||
return nil, fmt.Errorf("selector must not end with %q [line: %d]", openBrace, ln.no)
|
||||
}
|
||||
|
||||
if strings.HasSuffix(name, closeBrace) {
|
||||
return nil, fmt.Errorf("selector must not end with %q [line: %d]", closeBrace, ln.no)
|
||||
}
|
||||
|
||||
return &selector{
|
||||
elementBase: newElementBase(ln, parent),
|
||||
name: name,
|
||||
}, nil
|
||||
}
|
||||
62
vendor/github.com/yosssi/gcss/variable.go
generated
vendored
Normal file
62
vendor/github.com/yosssi/gcss/variable.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
package gcss
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// variable represents a GCSS variable.
|
||||
type variable struct {
|
||||
elementBase
|
||||
name string
|
||||
value string
|
||||
}
|
||||
|
||||
// WriteTo writes the variable to the writer.
|
||||
func (v *variable) WriteTo(w io.Writer) (int64, error) {
|
||||
n, err := w.Write([]byte(v.value))
|
||||
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
// variableNV extracts a variable name and value
|
||||
// from the line.
|
||||
func variableNV(ln *line) (string, string, error) {
|
||||
s := strings.TrimSpace(ln.s)
|
||||
|
||||
if !strings.HasPrefix(s, dollarMark) {
|
||||
return "", "", fmt.Errorf("variable must start with %q [line: %d]", dollarMark, ln.no)
|
||||
}
|
||||
|
||||
nv := strings.SplitN(s, space, 2)
|
||||
|
||||
if len(nv) < 2 {
|
||||
return "", "", fmt.Errorf("variable's name and value should be divided by a space [line: %d]", ln.no)
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(nv[0], colon) {
|
||||
return "", "", fmt.Errorf("variable's name should end with a colon [line: %d]", ln.no)
|
||||
}
|
||||
|
||||
return strings.TrimSuffix(strings.TrimPrefix(nv[0], dollarMark), colon), nv[1], nil
|
||||
}
|
||||
|
||||
// newVariable creates and returns a variable.
|
||||
func newVariable(ln *line, parent element) (*variable, error) {
|
||||
name, value, err := variableNV(ln)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if strings.HasSuffix(value, semicolon) {
|
||||
return nil, fmt.Errorf("variable must not end with %q", semicolon)
|
||||
}
|
||||
|
||||
return &variable{
|
||||
elementBase: newElementBase(ln, parent),
|
||||
name: name,
|
||||
value: value,
|
||||
}, nil
|
||||
}
|
||||
4
vendor/github.com/yosssi/gcss/version.go
generated
vendored
Normal file
4
vendor/github.com/yosssi/gcss/version.go
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
package gcss
|
||||
|
||||
// Version is the version of GCSS.
|
||||
const Version = "GCSS 0.1.0"
|
||||
39
vendor/github.com/yosssi/gcss/wercker.yml
generated
vendored
Normal file
39
vendor/github.com/yosssi/gcss/wercker.yml
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
box: yosssi/golang-latest@1.0.7
|
||||
# Build definition
|
||||
build:
|
||||
# The steps that will be executed on build
|
||||
steps:
|
||||
# Sets the go workspace and places you package
|
||||
# at the right place in the workspace tree
|
||||
- setup-go-workspace
|
||||
|
||||
# Gets the dependencies
|
||||
- script:
|
||||
name: go get
|
||||
code: |
|
||||
cd $WERCKER_SOURCE_DIR
|
||||
go version
|
||||
go get -t ./...
|
||||
|
||||
# Build the project
|
||||
- script:
|
||||
name: go build
|
||||
code: |
|
||||
go build ./...
|
||||
|
||||
# Test the project
|
||||
- script:
|
||||
name: go test
|
||||
code: |
|
||||
go test -cover -race ./...
|
||||
|
||||
# Invoke goveralls
|
||||
- script:
|
||||
name: goveralls
|
||||
code: |
|
||||
go get github.com/axw/gocov/gocov
|
||||
go get github.com/mattn/goveralls
|
||||
echo "mode: count" > all.cov
|
||||
packages=(. cmd/gcss)
|
||||
for package in ${packages[@]}; do go test --covermode=count -coverprofile=$package.cov ./$package; sed -e "1d" $package.cov >> all.cov; done
|
||||
GIT_BRANCH=$WERCKER_GIT_BRANCH goveralls -coverprofile=all.cov -service=wercker.com -repotoken $COVERALLS_REPO_TOKEN
|
||||
62
vendor/github.com/yosssi/gcss/write.go
generated
vendored
Normal file
62
vendor/github.com/yosssi/gcss/write.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
package gcss
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// writeFlusher is the interface that groups the basic Write and Flush methods.
|
||||
type writeFlusher interface {
|
||||
io.Writer
|
||||
Flush() error
|
||||
}
|
||||
|
||||
var newBufWriter = func(w io.Writer) writeFlusher {
|
||||
return bufio.NewWriter(w)
|
||||
}
|
||||
|
||||
// write writes the input byte data to the CSS file.
|
||||
func write(path string, bc <-chan []byte, berrc <-chan error) (<-chan struct{}, <-chan error) {
|
||||
done := make(chan struct{})
|
||||
errc := make(chan error)
|
||||
|
||||
go func() {
|
||||
f, err := os.Create(path)
|
||||
|
||||
if err != nil {
|
||||
errc <- err
|
||||
return
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
w := newBufWriter(f)
|
||||
|
||||
for {
|
||||
select {
|
||||
case b, ok := <-bc:
|
||||
if !ok {
|
||||
if err := w.Flush(); err != nil {
|
||||
errc <- err
|
||||
return
|
||||
}
|
||||
|
||||
done <- struct{}{}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := w.Write(b); err != nil {
|
||||
errc <- err
|
||||
return
|
||||
}
|
||||
case err := <-berrc:
|
||||
errc <- err
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return done, errc
|
||||
}
|
||||
Reference in New Issue
Block a user