core: initial commit
This commit is contained in:
commit
23fee42a20
|
@ -0,0 +1,2 @@
|
|||
compiled
|
||||
doc
|
|
@ -0,0 +1,10 @@
|
|||
# racket-sass
|
||||
|
||||
Racket bindings for [libsass].
|
||||
|
||||
## TODOs
|
||||
|
||||
* [ ] support for custom [`Sass_Options`](https://github.com/sass/libsass/blob/master/docs/api-context.md#basic-usage).
|
||||
|
||||
|
||||
[libsass]: https://github.com/sass/libsass
|
|
@ -0,0 +1,28 @@
|
|||
Copyright 2019 Bogdan Popa <bogdan@defn.io>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,32 @@
|
|||
#lang scribble/manual
|
||||
|
||||
@(require (for-label racket/base
|
||||
sass))
|
||||
|
||||
@title{@exec{SASS}: Bindings to libsass}
|
||||
@author[(author+email "Bogdan Popa" "bogdan@defn.io")]
|
||||
|
||||
|
||||
@section[#:tag "intro"]{Introduction}
|
||||
|
||||
@(define libsass-uri "https://github.com/sass/libsass")
|
||||
|
||||
@exec{sass} exposes bindings to @link[libsass-uri]{libsass} via the FFI.
|
||||
|
||||
|
||||
@section[#:tag "reference"]{Reference}
|
||||
@defmodule[sass]
|
||||
|
||||
@deftogether[
|
||||
(@defproc[(compile/file [path path-string?]) string?]
|
||||
@defproc[(compile/bytes [data bytes?]) string?]
|
||||
@defproc[(compile/string [data string?]) string?])]{
|
||||
|
||||
Compile a SCSS file, bytes or a string into a string of CSS. Raises
|
||||
@racket[exn:fail:sass?] on error.
|
||||
}
|
||||
|
||||
@deftogether[
|
||||
(@defproc[(exn:fail:sass? [v any/c]) boolean?]
|
||||
@defproc[(exn:fail:sass-code [e exn:fail:sass?]) exact-integer?])]{
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#lang info
|
||||
|
||||
(define version "0.0.0")
|
||||
(define collection "sass")
|
||||
(define deps '("base"))
|
||||
(define build-deps '("racket-doc"
|
||||
"rackunit-lib"
|
||||
"scribble-lib"))
|
||||
(define scribblings '(("doc.scrbl")))
|
|
@ -0,0 +1,117 @@
|
|||
#lang racket/base
|
||||
|
||||
(require racket/contract
|
||||
racket/string
|
||||
"private/libsass.rkt")
|
||||
|
||||
(provide
|
||||
(struct-out exn:fail:sass)
|
||||
|
||||
(rename-out [libsass_version sass-version]
|
||||
[libsass_language_version sass-language-version])
|
||||
|
||||
compile/file
|
||||
compile/bytes
|
||||
compile/string)
|
||||
|
||||
(struct exn:fail:sass exn:fail (code))
|
||||
|
||||
(define (raise-context-error context code)
|
||||
(define message (sass_context_get_error_message context))
|
||||
(raise (exn:fail:sass message (current-continuation-marks) code)))
|
||||
|
||||
(define/contract (compile/file path)
|
||||
(-> path-string? string?)
|
||||
(define context #f)
|
||||
|
||||
(dynamic-wind
|
||||
(lambda _
|
||||
(set! context (sass_make_file_context (path->complete-path path))))
|
||||
(lambda _
|
||||
(define code (sass_compile_file_context context))
|
||||
(case code
|
||||
[(0) (sass_context_get_output_string (sass_file_context_get_context context))]
|
||||
[else (raise-context-error (sass_file_context_get_context context) code)]))
|
||||
(lambda _
|
||||
(sass_delete_file_context context))))
|
||||
|
||||
(define/contract (compile/bytes data)
|
||||
(-> bytes? string?)
|
||||
(define context #f)
|
||||
|
||||
(dynamic-wind
|
||||
(lambda _
|
||||
;; Sass_Data_Context frees the string that gets passed into it after
|
||||
;; compilation so we have to copy the input string and ensure that the
|
||||
;; resulting copy isn't managed by the GC.
|
||||
(set! context (sass_make_data_context (bytes->unmanaged-cstring data))))
|
||||
(lambda ()
|
||||
(define code (sass_compile_data_context context))
|
||||
(case code
|
||||
[(0) (sass_context_get_output_string (sass_data_context_get_context context))]
|
||||
[else (raise-context-error (sass_data_context_get_context context) code)]))
|
||||
(lambda ()
|
||||
(sass_delete_data_context context))))
|
||||
|
||||
(define/contract (compile/string data)
|
||||
(-> non-empty-string? string?)
|
||||
(compile/bytes (string->bytes/utf-8 data)))
|
||||
|
||||
|
||||
(module+ test
|
||||
(require rackunit)
|
||||
|
||||
(test-case "can compile SCSS files to CSS"
|
||||
(define output
|
||||
(compile/file "resources/test.scss"))
|
||||
|
||||
(define expected #<<STYLE
|
||||
body {
|
||||
color: #fff; }
|
||||
|
||||
STYLE
|
||||
)
|
||||
|
||||
(check-equal? output expected))
|
||||
|
||||
(test-case "can compile SCSS strings to CSS"
|
||||
(define output
|
||||
(compile/string #<<STYLE
|
||||
$primary: red;
|
||||
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
color: $primary;
|
||||
}
|
||||
STYLE
|
||||
))
|
||||
|
||||
(define expected #<<STYLE
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
color: red; }
|
||||
|
||||
STYLE
|
||||
)
|
||||
|
||||
(check-equal? output expected))
|
||||
|
||||
(test-case "handles exceptions"
|
||||
(check-exn
|
||||
(lambda (e)
|
||||
(and (exn:fail:sass? e)
|
||||
(check-equal? (exn-message e) #<<MESSAGE
|
||||
Error: Invalid CSS after "a {": expected "}", was ""
|
||||
on line 1:3 of stdin
|
||||
>> a {
|
||||
--^
|
||||
|
||||
MESSAGE
|
||||
)))
|
||||
(lambda _
|
||||
(compile/string "a {")))))
|
|
@ -0,0 +1,71 @@
|
|||
#lang racket/base
|
||||
|
||||
(require ffi/unsafe
|
||||
ffi/unsafe/define)
|
||||
|
||||
(provide
|
||||
bytes->unmanaged-cstring
|
||||
|
||||
libsass_version
|
||||
libsass_language_version
|
||||
|
||||
sass_context_get_options
|
||||
sass_context_get_output_string
|
||||
sass_context_get_error_message
|
||||
|
||||
sass_make_data_context
|
||||
sass_delete_data_context
|
||||
sass_data_context_get_context
|
||||
sass_compile_data_context
|
||||
|
||||
sass_make_file_context
|
||||
sass_delete_file_context
|
||||
sass_file_context_get_context
|
||||
sass_compile_file_context)
|
||||
|
||||
(define (bytes->unmanaged-cstring bs)
|
||||
(define sz (bytes-length bs))
|
||||
(define p (malloc 'raw (add1 sz)))
|
||||
(begin0 p
|
||||
(memcpy p bs sz)
|
||||
(memset p sz 0 1)))
|
||||
|
||||
;; Basics ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-ffi-definer define-sass (ffi-lib "libsass"))
|
||||
|
||||
(define-sass libsass_version (_fun -> _string))
|
||||
(define-sass libsass_language_version (_fun -> _string))
|
||||
|
||||
|
||||
;; Sass_Options ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define _Sass_Options-pointer (_cpointer 'Sass_Options))
|
||||
|
||||
|
||||
;; Sass_Context ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define _Sass_Context-pointer (_cpointer 'Sass_Context))
|
||||
(define-sass sass_context_get_options (_fun _Sass_Context-pointer -> _Sass_Options-pointer))
|
||||
(define-sass sass_context_get_output_string (_fun _Sass_Context-pointer -> _string))
|
||||
(define-sass sass_context_get_error_message (_fun _Sass_Context-pointer -> _string))
|
||||
|
||||
|
||||
;; Sass_Data_Context ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define _Sass_Data_Context-pointer (_cpointer 'Sass_Data_Context))
|
||||
|
||||
(define-sass sass_make_data_context (_fun _pointer -> _Sass_Data_Context-pointer))
|
||||
(define-sass sass_delete_data_context (_fun _Sass_Data_Context-pointer -> _void))
|
||||
(define-sass sass_data_context_get_context (_fun _Sass_Data_Context-pointer -> _Sass_Context-pointer))
|
||||
(define-sass sass_compile_data_context (_fun _Sass_Data_Context-pointer -> _int))
|
||||
|
||||
|
||||
;; Sass_File_Context ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define _Sass_File_Context-pointer (_cpointer 'Sass_File_Context))
|
||||
|
||||
(define-sass sass_make_file_context (_fun _path -> _Sass_File_Context-pointer))
|
||||
(define-sass sass_delete_file_context (_fun _Sass_File_Context-pointer -> _void))
|
||||
(define-sass sass_file_context_get_context (_fun _Sass_File_Context-pointer -> _Sass_Context-pointer))
|
||||
(define-sass sass_compile_file_context (_fun _Sass_File_Context-pointer -> _int))
|
|
@ -0,0 +1,5 @@
|
|||
$a: #fff;
|
||||
|
||||
body {
|
||||
color: $a;
|
||||
}
|
Loading…
Reference in New Issue