Commit fe572eb1 by xzyfer Committed by Michael Mifsud
parent 639173e4
{ {
"name": "node-sass", "name": "node-sass",
"version": "4.7.2", "version": "4.7.2",
"libsass": "3.5.0.beta.2", "libsass": "3.5.0",
"description": "Wrapper around libsass", "description": "Wrapper around libsass",
"license": "MIT", "license": "MIT",
"bugs": "https://github.com/sass/node-sass/issues", "bugs": "https://github.com/sass/node-sass/issues",
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
...@@ -5,18 +5,18 @@ ...@@ -5,18 +5,18 @@
The following is a set of guidelines for contributing to LibSass, which is hosted in the [Sass Organization](https://github.com/sass) on GitHub. The following is a set of guidelines for contributing to LibSass, which is hosted in the [Sass Organization](https://github.com/sass) on GitHub.
These are just guidelines, not rules, use your best judgment and feel free to propose changes to this document in a pull request. These are just guidelines, not rules, use your best judgment and feel free to propose changes to this document in a pull request.
LibSass is a library that implements a [sass language] [8] compiler. As such it does not directly interface with end users (frontend developers). LibSass is a library that implements a [sass language][8] compiler. As such it does not directly interface with end users (frontend developers).
For direct contributions to the LibSass code base you will need to have at least a rough idea of C++, we will not lie about that. For direct contributions to the LibSass code base you will need to have at least a rough idea of C++, we will not lie about that.
But there are other ways to contribute to the progress of LibSass. All contributions are done via github pull requests. But there are other ways to contribute to the progress of LibSass. All contributions are done via github pull requests.
You can also contribute to the LibSass [documentation] [9] or provide additional [spec tests] [10] (and we will gladly point you in the You can also contribute to the LibSass [documentation][9] or provide additional [spec tests][10] (and we will gladly point you in the
direction for corners that lack test coverage). Foremost we rely on good and concise bug reports for issues the spec tests do not yet catch. direction for corners that lack test coverage). Foremost we rely on good and concise bug reports for issues the spec tests do not yet catch.
## Precheck: My Sass isn't compiling ## Precheck: My Sass isn't compiling
- [ ] Check if you can reproduce the issue via [SourceMap Inspector] [5] (updated regularly). - [ ] Check if you can reproduce the issue via [SourceMap Inspector][5] (updated regularly).
- [ ] Validate official ruby sass compiler via [SassMeister] [6] produces your expected result. - [ ] Validate official ruby sass compiler via [SassMeister][6] produces your expected result.
- [ ] Search for similar issue in [LibSass] [1] and [node-sass] [2] (include closed tickets) - [ ] Search for similar issue in [LibSass][1] and [node-sass][2] (include closed tickets)
- [ ] Optionally test your code directly with [sass] [7] or [sassc] [3] ([installer] [4]) - [ ] Optionally test your code directly with [sass][7] or [sassc][3] ([installer][4])
## Precheck: My build/install fails ## Precheck: My build/install fails
- [ ] Problems with building or installing libsass should be directed to implementors first! - [ ] Problems with building or installing libsass should be directed to implementors first!
...@@ -47,7 +47,7 @@ direction for corners that lack test coverage). Foremost we rely on good and con ...@@ -47,7 +47,7 @@ direction for corners that lack test coverage). Foremost we rely on good and con
## What makes a code test case ## What makes a code test case
Important is that someone else can get the test case up and running to reproduce it locally. For this Important is that someone else can get the test case up and running to reproduce it locally. For this
we urge you to verify that your sample yields the expected result by testing it via [SassMeister] [6] we urge you to verify that your sample yields the expected result by testing it via [SassMeister][6]
or directly via ruby sass or node-sass (or any other libsass implementor) before submitting your bug or directly via ruby sass or node-sass (or any other libsass implementor) before submitting your bug
report. Once you verified all of the above, you may use the template below to file your bug report. report. Once you verified all of the above, you may use the template below to file your bug report.
......
### Title: Be as meaningful as possible in 60 chars if possible [todo]: # (Title: Be as meaningful as possible)
[todo]: # (Title: Try to use 60 or less chars)
[todo]: # (This is only a template!)
[todo]: # (remove unneeded bits)
[todo]: # (use github preview!)
## input.scss
[todo]: # (always test and report with scss syntax)
[todo]: # (use sass only when results differ from scss)
input.scss
```scss ```scss
test { test {
content: bar content: bar
} }
``` ```
[libsass 3.5.5] [1] ## Actual results
[todo]: # (update version info!)
[libsass 3.X.y][1]
```css ```css
test { test {
content: bar; } content: bar; }
``` ```
ruby sass 3.4.21 ## Expected result
[todo]: # (update version info!)
ruby sass 3.X.y
```css ```css
test { test {
content: bar; } content: bar; }
``` ```
[todo]: # (update version info!)
[todo]: # (example for node-sass!)
version info: version info:
```cmd ```cmd
$ node-sass --version $ node-sass --version
node-sass 3.3.3 (Wrapper) [JavaScript] node-sass 3.X.y (Wrapper) [JavaScript]
libsass 3.2.5 (Sass Compiler) [C/C++] libsass 3.X.y (Sass Compiler) [C/C++]
``` ```
[todo]: # (Go to http://libsass.ocbnet.ch/srcmap)
[todo]: # (Enter your SCSS code and hit compile)
[todo]: # (Click `bookmark` and replace the url)
[todo]: # (link is used in actual results above)
[1]: http://libsass.ocbnet.ch/srcmap/#dGVzdCB7CiAgY29udGVudDogYmFyOyB9Cg== [1]: http://libsass.ocbnet.ch/srcmap/#dGVzdCB7CiAgY29udGVudDogYmFyOyB9Cg==
...@@ -12,6 +12,8 @@ VERSION ...@@ -12,6 +12,8 @@ VERSION
.cproject .cproject
.project .project
.settings/ .settings/
*.db
*.aps
# Configuration stuff # Configuration stuff
...@@ -68,6 +70,7 @@ bin/* ...@@ -68,6 +70,7 @@ bin/*
.libs/ .libs/
win/bin win/bin
*.user *.user
win/*.db
# Final results # Final results
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
...@@ -69,7 +69,7 @@ else ...@@ -69,7 +69,7 @@ else
endif endif
SASS_TESTER = $(RUBY) $(SASS_SPEC_PATH)/sass-spec.rb SASS_TESTER = $(RUBY) $(SASS_SPEC_PATH)/sass-spec.rb
SASS_TESTER += -c $(SASS_LIBSASS_PATH)/tester$(EXEEXT) SASS_TESTER += -c $(top_srcdir)/tester$(EXEEXT)
test: test:
$(SASS_TESTER) $(LOG_FLAGS) $(SASS_SPEC_PATH) $(SASS_TEST_FLAGS) $(SASS_TESTER) $(LOG_FLAGS) $(SASS_SPEC_PATH) $(SASS_TEST_FLAGS)
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
...@@ -299,7 +299,7 @@ install-shared: $(DESTDIR)$(PREFIX)/lib/libsass.so \ ...@@ -299,7 +299,7 @@ install-shared: $(DESTDIR)$(PREFIX)/lib/libsass.so \
install-headers install-headers
$(SASSC_BIN): $(BUILD) $(SASSC_BIN): $(BUILD)
$(MAKE) -C $(SASS_SASSC_PATH) $(MAKE) -C $(SASS_SASSC_PATH) build-$(BUILD)-dev
sassc: $(SASSC_BIN) sassc: $(SASSC_BIN)
$(SASSC_BIN) -v $(SASSC_BIN) -v
......
File mode changed from 100755 to 100644
LibSass LibSass - Sass compiler written in C++
======= ======================================
by Aaron Leung ([@akhleung]), Hampton Catlin ([@hcatlin]), Marcel Greter ([@mgreter]) and Michael Mifsud ([@xzyfer]) Currently maintained by Marcel Greter ([@mgreter]) and Michael Mifsud ([@xzyfer])
Originally created by Aaron Leung ([@akhleung]) and Hampton Catlin ([@hcatlin])
[![Unix CI](https://travis-ci.org/sass/libsass.svg?branch=master)](https://travis-ci.org/sass/libsass)
[![Windows CI](https://ci.appveyor.com/api/projects/status/github/sass/libsass?svg=true)](https://ci.appveyor.com/project/sass/libsass/branch/master) [![Unix CI](https://travis-ci.org/sass/libsass.svg?branch=master)](https://travis-ci.org/sass/libsass "Travis CI")
[![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=283068)](https://www.bountysource.com/trackers/283068-libsass?utm_source=283068&utm_medium=shield&utm_campaign=TRACKER_BADGE) [![Windows CI](https://ci.appveyor.com/api/projects/status/github/sass/libsass?svg=true)](https://ci.appveyor.com/project/sass/libsass/branch/master "Appveyor CI")
[![Coverage Status](https://img.shields.io/coveralls/sass/libsass.svg)](https://coveralls.io/r/sass/libsass?branch=feature%2Ftest-travis-ci-3) [![Coverage Status](https://img.shields.io/coveralls/sass/libsass.svg)](https://coveralls.io/r/sass/libsass?branch=feature%2Ftest-travis-ci-3 "Code coverage of spec tests")
[![Join us](https://libsass-slack.herokuapp.com/badge.svg)](https://libsass-slack.herokuapp.com/) [![Percentage of issues still open](http://isitmaintained.com/badge/open/sass/libsass.svg)](http://isitmaintained.com/project/sass/libsass "Percentage of issues still open")
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/sass/libsass.svg)](http://isitmaintained.com/project/sass/libsass "Average time to resolve an issue")
https://github.com/sass/libsass [![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=283068)](https://www.bountysource.com/trackers/283068-libsass?utm_source=283068&utm_medium=shield&utm_campaign=TRACKER_BADGE "Bountysource")
[![Join us](https://libsass-slack.herokuapp.com/badge.svg)](https://libsass-slack.herokuapp.com/ "Slack communication channels")
LibSass is just a library, but if you want to RUN LibSass,
then go to https://github.com/sass/sassc or
https://github.com/sass/sassc-ruby or [LibSass](https://github.com/sass/libsass "LibSass GitHub Project") is just a library!
[find your local implementer](docs/implementations.md). If you want to use LibSass to compile Sass, you need an implementer. Some
implementations are only bindings into other programming languages. But most also
LibSass requires GCC 4.6+ or Clang/LLVM. If your OS is older, this version may not compile. ship with a command line interface (CLI) you can use directly. There is also
[SassC](https://github.com/sass/sassc), which is the official lightweight
On Windows, you need MinGW with GCC 4.6+ or VS 2013 Update 4+. It is also possible to build LibSass with Clang/LLVM on Windows. CLI tool built by the same people as LibSass.
### Excerpt of "sanctioned" implementations:
- https://github.com/sass/node-sass (Node.js)
- https://github.com/sass/perl-libsass (Perl)
- https://github.com/sass/libsass-python (Python)
- https://github.com/wellington/go-libsass (Go)
- https://github.com/sass/sassc-ruby (Ruby)
- https://github.com/sass/libsass-net (C#)
- https://github.com/medialize/sass.js (JS)
- https://github.com/bit3/jsass (Java)
This list does not say anything about the quality of either the listed or not listed [implementations](docs/implementations.md)!
The authors of the listed projects above are just known to work regularly together with LibSass developers.
About About
----- -----
LibSass is a C/C++ port of the Sass CSS precompiler. The original version was written in Ruby, but this version is meant for efficiency and portability. LibSass is a C++ port of the original Ruby Sass CSS compiler with a [C API](docs/api-doc.md).
We coded LibSass with portability and efficiency in mind. You can expect LibSass to be a lot
This library strives to be light, simple, and easy to build and integrate with a variety of platforms and languages. faster than Ruby Sass and on par or faster than the best alternative CSS compilers around.
Developing Developing
---------- ----------
As you may have noticed, the LibSass repo itself has As noted above, the LibSass repository does not contain any binaries or other way to execute
no executables and no tests. Oh noes! How can you develop??? LibSass. Therefore, you need an implementer to develop LibSass. Easiest is to start with
the official [SassC](http://github.com/sass/sassc) CLI wrapper. It is *guaranteed* to compile
Well, luckily, [SassC](http://github.com/sass/sassc) is the official binary wrapper for with the latest code in LibSass master, since it is also used in the CI process. There is no
LibSass and is *always* kept in sync. SassC is used by continous integration systems in limitation here, as you may use any other LibSass implementer to test your LibSass branch!
LibSass repository. When developing LibSass, it is best to actually
checkout SassC and develop in that directory with the SassC spec
and tests there.
We even run Travis tests for SassC!
Tests Testing
------- -------
Since LibSass is a pure library, tests are run through the [SassSpec](https://github.com/sass/sass-spec) project using the [SassC](http://github.com/sass/sassc) driver. Since LibSass is a pure library, tests are run through the [Sass-Spec](https://github.com/sass/sass-spec)
project using the [SassC](http://github.com/sass/sassc) CLI wrapper. To run the tests against LibSass while
developing, you can run `./script/spec`. This will clone SassC and Sass-Spec under the project folder and
then run the Sass-Spec test suite. You may want to update the clones to ensure you have the latest version.
Note that the scripts in the `./script` folder are mainly intended for our CI needs.
To run tests against LibSass while developing, you can run `./script/spec`. This will clone SassC and Sass-Spec under the project folder and then run the Sass-Spec test suite. You may want to update the clones to ensure you have the latest version. Building
--------
### DEBUG builds To build LibSass you need GCC 4.6+ or Clang/LLVM. If your OS is older, you may need to upgrade
them first (or install clang as an alternative). On Windows, you need MinGW with GCC 4.6+ or VS 2013
Update 4+. It is also possible to build LibSass with Clang/LLVM on Windows with various build chains
and/or command line interpreters.
Set the environment variable `DEBUG` to `1` to enable debug builds that can be debugged See the [build docs for further instructions](docs/build.md)!
with `gdb`, `lldb` and others. E.g.: use `$ DEBUG=1 ./script/spec` to run the tests with
a debug build.
Library Usage Compatibility
------------- -------------
While LibSass is a library primarily written in C++, it provides a simple Current LibSass 3.4 should be compatible with Sass 3.4. Please refer to the [sass compatibility
C interface which should be used by most implementers. LibSass does not do page](http://sass-compatibility.github.io/) for a more detailed comparison. But note that there
much on its own without an implementer. This can be a command line tool, like are still a few incomplete edges which we are aware of. Otherwise LibSass has reached a good level
[sassc](https://github.com/sass/sassc) or a [binding](docs/implementations.md) of stability, thanks to our ever growing [Sass-Spec test suite](https://github.com/sass/sass-spec).
to your favorite programing language.
If you want to build or interface with LibSass, we recommend to check out the
documentation pages about [building LibSass](docs/build.md) and
the [C-API documentation](docs/api-doc.md).
About Sass About Sass
---------- ----------
Sass is a CSS pre-processor language to add on exciting, new, Sass is a CSS pre-processor language to add on exciting, new, awesome features to CSS. Sass was
awesome features to CSS. Sass was the first language of its kind the first language of its kind and by far the most mature and up to date codebase.
and by far the most mature and up to date codebase.
Sass was originally concieved of by the co-creator of this library, Sass was originally conceived of by the co-creator of this library, Hampton Catlin ([@hcatlin]).
Hampton Catlin ([@hcatlin]). Most of the language has been the result of years Most of the language has been the result of years of work by Natalie Weizenbaum ([@nex3]) and
of work by Natalie Weizenbaum ([@nex3]) and Chris Eppstein ([@chriseppstein]). Chris Eppstein ([@chriseppstein]).
For more information about Sass itself, please visit http://sass-lang.com For more information about Sass itself, please visit http://sass-lang.com
Initial development of libsass by Aaron Leung and Hampton Catlin was supported by [Moovweb](http://www.moovweb.com). Initial development of LibSass by Aaron Leung and Hampton Catlin was supported by [Moovweb](http://www.moovweb.com).
Licensing Licensing
--------- ---------
Our MIT license is designed to be as simple, and liberal as possible. Our [MIT license](LICENSE) is designed to be as simple and liberal as possible.
sass2scss was originally written by [Marcel Greter][@mgreter]
and he happily agreed to have it merged into the project.
[@hcatlin]: https://github.com/hcatlin [@hcatlin]: https://github.com/hcatlin
[@akhleung]: https://github.com/akhleung [@akhleung]: https://github.com/akhleung
......
File mode changed from 100755 to 100644
...@@ -7,8 +7,13 @@ environment: ...@@ -7,8 +7,13 @@ environment:
matrix: matrix:
- Compiler: msvc - Compiler: msvc
Config: Release Config: Release
Platform: Win32
- Compiler: msvc - Compiler: msvc
Config: Debug Config: Debug
Platform: Win32
- Compiler: msvc
Config: Release
Platform: Win64
- Compiler: mingw - Compiler: mingw
Build: static Build: static
- Compiler: mingw - Compiler: mingw
...@@ -38,7 +43,7 @@ build_script: ...@@ -38,7 +43,7 @@ build_script:
if ($env:Compiler -eq "mingw") { if ($env:Compiler -eq "mingw") {
mingw32-make -j4 sassc mingw32-make -j4 sassc
} else { } else {
msbuild /m:4 /p:Configuration=$env:Config sassc\win\sassc.sln msbuild /m:4 /p:"Configuration=$env:Config;Platform=$env:Platform" sassc\win\sassc.sln
} }
# print the branding art # print the branding art
...@@ -84,4 +89,3 @@ test_script: ...@@ -84,4 +89,3 @@ test_script:
} else { } else {
echo "Success!" echo "Success!"
} }
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
...@@ -187,7 +187,7 @@ should be on par with the latest LibSass interface version. Some of them may not ...@@ -187,7 +187,7 @@ should be on par with the latest LibSass interface version. Some of them may not
have all features implemented! have all features implemented!
1. [Perl Example](https://github.com/sass/perl-libsass/blob/master/lib/CSS/Sass.xs) 1. [Perl Example](https://github.com/sass/perl-libsass/blob/master/lib/CSS/Sass.xs)
2. [Go Example](http://godoc.org/github.com/wellington/go-libsass#example-Context-Compile) 2. [Go Example](https://godoc.org/github.com/wellington/go-libsass#example-Compiler--Stdin)
3. [Node Example](https://github.com/sass/node-sass/blob/master/src/binding.cpp) 3. [Node Example](https://github.com/sass/node-sass/blob/master/src/binding.cpp)
## ABI forward compatibility ## ABI forward compatibility
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
`Sass_Values` are used to pass values and their types between the implementer `Sass_Values` are used to pass values and their types between the implementer
and LibSass. Sass knows various different value types (including nested arrays and LibSass. Sass knows various different value types (including nested arrays
and hash-maps). If you implement a binding to another programming language, you and hash-maps). If you implement a binding to another programming language, you
have to find a way to [marshal] [1] (convert) `Sass_Values` between the target have to find a way to [marshal][1] (convert) `Sass_Values` between the target
language and C. `Sass_Values` are currently only used by custom functions, but language and C. `Sass_Values` are currently only used by custom functions, but
it should also be possible to use them without a compiler context. it should also be possible to use them without a compiler context.
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
...@@ -3,14 +3,14 @@ Both should be considered experimental (MinGW was better tested)! ...@@ -3,14 +3,14 @@ Both should be considered experimental (MinGW was better tested)!
## Building via MingGW (makefiles) ## Building via MingGW (makefiles)
First grab the latest [MinGW for windows] [1] installer. Once it is installed, you can click on continue or open the Installation Manager via `bin\mingw-get.exe`. First grab the latest [MinGW for windows][1] installer. Once it is installed, you can click on continue or open the Installation Manager via `bin\mingw-get.exe`.
You need to have the following components installed: You need to have the following components installed:
![Visualization of components installed in the interface](https://cloud.githubusercontent.com/assets/282293/5525466/947bf396-89e6-11e4-841d-4aa916f14de1.png) ![Visualization of components installed in the interface](https://cloud.githubusercontent.com/assets/282293/5525466/947bf396-89e6-11e4-841d-4aa916f14de1.png)
Next we need to install [git for windows] [2]. You probably want to check the option to add it to the global path, but you do not need to install the unix tools. Next we need to install [git for windows][2]. You probably want to check the option to add it to the global path, but you do not need to install the unix tools.
If you want to run the spec test-suite you also need [ruby] [3] and a few gems available. Grab the [latest installer] [3] and make sure to add it the global path. Then install the missing gems: If you want to run the spec test-suite you also need [ruby][3] and a few gems available. Grab the [latest installer][3] and make sure to add it the global path. Then install the missing gems:
```bash ```bash
gem install minitest gem install minitest
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
## Building LibSass with MingGW (makefiles) ## Building LibSass with MingGW (makefiles)
First grab the latest [MinGW for windows] [1] installer. Once it is installed, you can click on continue or open the Installation Manager via `bin\mingw-get.exe`. First grab the latest [MinGW for windows][1] installer. Once it is installed, you can click on continue or open the Installation Manager via `bin\mingw-get.exe`.
You need to have the following components installed: You need to have the following components installed:
![](https://cloud.githubusercontent.com/assets/282293/5525466/947bf396-89e6-11e4-841d-4aa916f14de1.png) ![](https://cloud.githubusercontent.com/assets/282293/5525466/947bf396-89e6-11e4-841d-4aa916f14de1.png)
Next we need to install [git for windows] [2]. You probably want to check the option to add it to the global path, but you do not need to install the unix tools. Next we need to install [git for windows][2]. You probably want to check the option to add it to the global path, but you do not need to install the unix tools.
If you want to run the spec test-suite you also need [ruby] [3] and a few gems available. Grab the [latest installer] [3] and make sure to add it the global path. Then install the missing gems: If you want to run the spec test-suite you also need [ruby][3] and a few gems available. Grab the [latest installer][3] and make sure to add it the global path. Then install the missing gems:
```bash ```bash
gem install minitest gem install minitest
......
File mode changed from 100755 to 100644
`libsass` is only a library and does not do much on its own. You need an implementation that you can use from the [command line] [6]. Or some [[bindings|Implementations]] to use it within your favorite programming language. You should be able to get [`sassc`] [6] running by following the instructions in this guide. `libsass` is only a library and does not do much on its own. You need an implementation that you can use from the [command line][6]. Or some [bindings|Implementations][9] to use it within your favorite programming language. You should be able to get [`sassc`][6] running by following the instructions in this guide.
Before starting, see [setup dev environment](setup-environment.md). Before starting, see [setup dev environment](setup-environment.md).
...@@ -11,27 +11,27 @@ We try to keep the code as OS independent and standard compliant as possible. Re ...@@ -11,27 +11,27 @@ We try to keep the code as OS independent and standard compliant as possible. Re
Linux is the main target for `libsass` and we support two ways to build `libsass` here. The old plain makefiles should still work on most systems (including MinGW), while the autotools build is preferred if you want to create a [system library] (experimental). Linux is the main target for `libsass` and we support two ways to build `libsass` here. The old plain makefiles should still work on most systems (including MinGW), while the autotools build is preferred if you want to create a [system library] (experimental).
- [Building with makefiles] [1] - [Building with makefiles][1]
- [Building with autotools] [2] - [Building with autotools][2]
### Building on Windows (experimental) ### Building on Windows (experimental)
Windows build support was added very recently and should be considered experimental. Credits go to @darrenkopp and @am11 for their work on getting `libsass` and `sassc` to compile with visual studio! Windows build support was added very recently and should be considered experimental. Credits go to @darrenkopp and @am11 for their work on getting `libsass` and `sassc` to compile with visual studio!
- [Building with MinGW] [3] - [Building with MinGW][3]
- [Building with Visual Studio] [11] - [Building with Visual Studio][11]
### Building on Max OS X (untested) ### Building on Max OS X (untested)
Works the same as on linux, but you can also install LibSass via `homebrew`. Works the same as on linux, but you can also install LibSass via `homebrew`.
- [Building on Mac OS X] [10] - [Building on Mac OS X][10]
### Building a system library (experimental) ### Building a system library (experimental)
Since `libsass` is a library, it makes sense to install it as a shared library on your system. On linux this means creating a `.so` library via autotools. This should work pretty well already, but we are not yet committed to keep the ABI 100% stable. This should be the case once we increase the version number for the library to 1.0.0 or higher. On Windows you should be able get a `dll` by creating a shared build with MinGW. There is currently no target in the MSVC project files to do this. Since `libsass` is a library, it makes sense to install it as a shared library on your system. On linux this means creating a `.so` library via autotools. This should work pretty well already, but we are not yet committed to keep the ABI 100% stable. This should be the case once we increase the version number for the library to 1.0.0 or higher. On Windows you should be able get a `dll` by creating a shared build with MinGW. There is currently no target in the MSVC project files to do this.
- [Building shared system library] [4] - [Building shared system library][4]
Compiling with clang instead of gcc Compiling with clang instead of gcc
-- --
...@@ -46,7 +46,7 @@ export CXX=/usr/bin/clang++ ...@@ -46,7 +46,7 @@ export CXX=/usr/bin/clang++
Running the spec test-suite Running the spec test-suite
-- --
We constantly and automatically test `libsass` against the official [spec test-suite] [5]. To do this we need to have a test-runner (which is written in ruby) and a command-line tool ([`sassc`] [6]) to run the tests. Therefore we need to additionally compile `sassc`. To do this, the build files of all three projects need to work together. This may not have the same quality for all build flavors. You definitely need to have ruby (2.1?) installed (version 1.9 seems to cause problems at least on windows). You also need some gems installed: We constantly and automatically test `libsass` against the official [spec test-suite][5]. To do this we need to have a test-runner (which is written in ruby) and a command-line tool ([`sassc`][6]) to run the tests. Therefore we need to additionally compile `sassc`. To do this, the build files of all three projects need to work together. This may not have the same quality for all build flavors. You definitely need to have ruby (2.1?) installed (version 1.9 seems to cause problems at least on windows). You also need some gems installed:
```bash ```bash
ruby -v ruby -v
...@@ -67,7 +67,7 @@ export LIBSASS_VERSION="x.y.z." ...@@ -67,7 +67,7 @@ export LIBSASS_VERSION="x.y.z."
Continuous Integration Continuous Integration
-- --
We use two CI services to automatically test all commits against the latest [spec test-suite] [5]. We use two CI services to automatically test all commits against the latest [spec test-suite][5].
- [LibSass on Travis-CI (linux)][7] - [LibSass on Travis-CI (linux)][7]
[![Build Status](https://travis-ci.org/sass/libsass.png?branch=master)](https://travis-ci.org/sass/libsass) [![Build Status](https://travis-ci.org/sass/libsass.png?branch=master)](https://travis-ci.org/sass/libsass)
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#ifndef SASS2SCSS_VERSION #ifndef SASS2SCSS_VERSION
// Hardcode once the file is copied from // Hardcode once the file is copied from
// https://github.com/mgreter/sass2scss // https://github.com/mgreter/sass2scss
#define SASS2SCSS_VERSION "1.1.0" #define SASS2SCSS_VERSION "1.1.1"
#endif #endif
// add namespace for c++ // add namespace for c++
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
...@@ -18,18 +18,18 @@ BEGIN ...@@ -18,18 +18,18 @@ BEGIN
BEGIN BEGIN
BLOCK "080904b0" BLOCK "080904b0"
BEGIN BEGIN
VALUE "CompanyName", "Libsass Organization" VALUE "CompanyName", "Sass Open Source Foundation"
VALUE "FileDescription", "A C/C++ implementation of a Sass compiler" VALUE "FileDescription", "A C/C++ implementation of a Sass compiler"
VALUE "FileVersion", "0.9.0.0" VALUE "FileVersion", "1.0.0.0"
VALUE "InternalName", "libsass" VALUE "InternalName", "libsass"
VALUE "LegalCopyright", "©2014 libsass.org" VALUE "LegalCopyright", "\251 2017 libsass.org"
VALUE "OriginalFilename", "libsass.dll" VALUE "OriginalFilename", "libsass.dll"
VALUE "ProductName", "Libsass Library" VALUE "ProductName", "LibSass Library"
VALUE "ProductVersion", "0.9.0.0" VALUE "ProductVersion", "1.0.0.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"
BEGIN BEGIN
VALUE "Translation", 0x809, 1200 VALUE "Translation", 0x809, 1200
END END
END END
\ No newline at end of file
...@@ -114,7 +114,7 @@ then ...@@ -114,7 +114,7 @@ then
then then
echo "Travis rate limit on github exceeded" echo "Travis rate limit on github exceeded"
echo "Retrying via 'special purpose proxy'" echo "Retrying via 'special purpose proxy'"
JSON=$(curl -L -sS http://libsass.ocbnet.ch/libsass-spec-pr.psgi/$TRAVIS_PULL_REQUEST) JSON=$(curl -L -sS https://github-api-reverse-proxy.herokuapp.com/repos/sass/libsass/pulls/$TRAVIS_PULL_REQUEST)
fi fi
RE_SPEC_PR="sass\/sass-spec(#|\/pull\/)([0-9]+)" RE_SPEC_PR="sass\/sass-spec(#|\/pull\/)([0-9]+)"
......
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
gem install minitest gem install minitest
gem install minitap gem install minitap
pip install --user 'requests[security]' pip2 install --user 'requests[security]'
#!/bin/bash #!/bin/bash
if [ "x$COVERAGE" == "xyes" ]; then if [ "x$COVERAGE" == "xyes" ]; then
pip install --user gcovr pip2 install --user gcovr
pip install --user cpp-coveralls pip2 install --user cpp-coveralls
else else
echo "no dependencies to install" echo "no dependencies to install"
fi fi
...@@ -15,9 +15,6 @@ if [ "x$AUTOTOOLS" == "xyes" ]; then ...@@ -15,9 +15,6 @@ if [ "x$AUTOTOOLS" == "xyes" ]; then
sudo apt-get -qq install automake sudo apt-get -qq install automake
fi fi
# https://github.com/sass/libsass/pull/2183
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
brew uninstall libtool
brew install libtool
fi
fi fi
exit 0
#! /bin/sh #!/usr/bin/env sh
# Copyright (C) 2011-2013 Free Software Foundation, Inc. # Copyright (C) 2011-2013 Free Software Foundation, Inc.
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
......
File mode changed from 100755 to 100644
...@@ -19,12 +19,21 @@ class LocalOption { ...@@ -19,12 +19,21 @@ class LocalOption {
this->orig = var; this->orig = var;
*(this->var) = orig; *(this->var) = orig;
} }
void reset()
{
*(this->var) = this->orig;
}
~LocalOption() { ~LocalOption() {
*(this->var) = this->orig; *(this->var) = this->orig;
} }
}; };
#define LOCAL_FLAG(name,opt) LocalOption<bool> flag_##name(name, opt) #define LOCAL_FLAG(name,opt) LocalOption<bool> flag_##name(name, opt)
#define LOCAL_COUNT(name,opt) LocalOption<size_t> cnt_##name(name, opt)
#define NESTING_GUARD(name) \
LocalOption<size_t> cnt_##name(name, name + 1); \
if (name > MAX_NESTING) throw Exception::NestingLimitError(pstate); \
#define ATTACH_OPERATIONS()\ #define ATTACH_OPERATIONS()\
virtual void perform(Operation<void>* op) { (*op)(this); }\ virtual void perform(Operation<void>* op) { (*op)(this); }\
......
File mode changed from 100755 to 100644
...@@ -132,6 +132,9 @@ namespace Sass { ...@@ -132,6 +132,9 @@ namespace Sass {
class Map; class Map;
typedef Map* Map_Ptr; typedef Map* Map_Ptr;
typedef Map const* Map_Ptr_Const; typedef Map const* Map_Ptr_Const;
class Function;
typedef Function* Function_Ptr;
typedef Function const* Function_Ptr_Const;
class Mixin_Call; class Mixin_Call;
typedef Mixin_Call* Mixin_Call_Ptr; typedef Mixin_Call* Mixin_Call_Ptr;
...@@ -158,9 +161,6 @@ namespace Sass { ...@@ -158,9 +161,6 @@ namespace Sass {
class Variable; class Variable;
typedef Variable* Variable_Ptr; typedef Variable* Variable_Ptr;
typedef Variable const* Variable_Ptr_Const; typedef Variable const* Variable_Ptr_Const;
class Textual;
typedef Textual* Textual_Ptr;
typedef Textual const* Textual_Ptr_Const;
class Number; class Number;
typedef Number* Number_Ptr; typedef Number* Number_Ptr;
typedef Number const* Number_Ptr_Const; typedef Number const* Number_Ptr_Const;
...@@ -314,6 +314,7 @@ namespace Sass { ...@@ -314,6 +314,7 @@ namespace Sass {
IMPL_MEM_OBJ(Expression); IMPL_MEM_OBJ(Expression);
IMPL_MEM_OBJ(List); IMPL_MEM_OBJ(List);
IMPL_MEM_OBJ(Map); IMPL_MEM_OBJ(Map);
IMPL_MEM_OBJ(Function);
IMPL_MEM_OBJ(Binary_Expression); IMPL_MEM_OBJ(Binary_Expression);
IMPL_MEM_OBJ(Unary_Expression); IMPL_MEM_OBJ(Unary_Expression);
IMPL_MEM_OBJ(Function_Call); IMPL_MEM_OBJ(Function_Call);
...@@ -321,7 +322,6 @@ namespace Sass { ...@@ -321,7 +322,6 @@ namespace Sass {
IMPL_MEM_OBJ(Custom_Warning); IMPL_MEM_OBJ(Custom_Warning);
IMPL_MEM_OBJ(Custom_Error); IMPL_MEM_OBJ(Custom_Error);
IMPL_MEM_OBJ(Variable); IMPL_MEM_OBJ(Variable);
IMPL_MEM_OBJ(Textual);
IMPL_MEM_OBJ(Number); IMPL_MEM_OBJ(Number);
IMPL_MEM_OBJ(Color); IMPL_MEM_OBJ(Color);
IMPL_MEM_OBJ(Boolean); IMPL_MEM_OBJ(Boolean);
...@@ -376,6 +376,11 @@ namespace Sass { ...@@ -376,6 +376,11 @@ namespace Sass {
struct CompareNodes { struct CompareNodes {
template <class T> template <class T>
bool operator() (const T& lhs, const T& rhs) const { bool operator() (const T& lhs, const T& rhs) const {
// code around sass logic issue. 1px == 1 is true
// but both items are still different keys in maps
if (dynamic_cast<Number*>(lhs.ptr()))
if (dynamic_cast<Number*>(rhs.ptr()))
return lhs->hash() == rhs->hash();
return !lhs.isNull() && !rhs.isNull() && *lhs == *rhs; return !lhs.isNull() && !rhs.isNull() && *lhs == *rhs;
} }
}; };
...@@ -410,8 +415,12 @@ namespace Sass { ...@@ -410,8 +415,12 @@ namespace Sass {
typedef std::deque<Complex_Selector_Obj> ComplexSelectorDeque; typedef std::deque<Complex_Selector_Obj> ComplexSelectorDeque;
typedef std::set<Simple_Selector_Obj, OrderNodes> SimpleSelectorSet; typedef std::set<Simple_Selector_Obj, OrderNodes> SimpleSelectorSet;
typedef std::set<Complex_Selector_Obj, OrderNodes> ComplexSelectorSet; typedef std::set<Complex_Selector_Obj, OrderNodes> ComplexSelectorSet;
typedef std::set<Compound_Selector_Obj, OrderNodes> CompoundSelectorSet;
typedef std::unordered_set<Simple_Selector_Obj, HashNodes, CompareNodes> SimpleSelectorDict; typedef std::unordered_set<Simple_Selector_Obj, HashNodes, CompareNodes> SimpleSelectorDict;
// only to switch implementations for testing
#define environment_map std::map
// ########################################################################### // ###########################################################################
// explicit type conversion functions // explicit type conversion functions
// ########################################################################### // ###########################################################################
......
File mode changed from 100755 to 100644
...@@ -24,7 +24,9 @@ namespace base64 ...@@ -24,7 +24,9 @@ namespace base64
encoder(int buffersize_in = BUFFERSIZE) encoder(int buffersize_in = BUFFERSIZE)
: _buffersize(buffersize_in) : _buffersize(buffersize_in)
{} {
base64_init_encodestate(&_state);
}
int encode(char value_in) int encode(char value_in)
{ {
......
...@@ -60,13 +60,13 @@ namespace Sass { ...@@ -60,13 +60,13 @@ namespace Sass {
size_t depth() size_t depth()
{ {
size_t d = 0; size_t d = std::string::npos;
Backtrace* p = parent; Backtrace* p = parent;
while (p) { while (p) {
++d; ++d;
p = p->parent; p = p->parent;
} }
return d-1; return d;
} }
}; };
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
...@@ -14,6 +14,8 @@ namespace Sass { ...@@ -14,6 +14,8 @@ namespace Sass {
std::string callee(type + " " + name); std::string callee(type + " " + name);
std::map<std::string, Parameter_Obj> param_map; std::map<std::string, Parameter_Obj> param_map;
List_Obj varargs = SASS_MEMORY_NEW(List, as->pstate());
varargs->is_arglist(true); // enable keyword size handling
for (size_t i = 0, L = as->length(); i < L; ++i) { for (size_t i = 0, L = as->length(); i < L; ++i) {
if (auto str = Cast<String_Quoted>((*as)[i]->value())) { if (auto str = Cast<String_Quoted>((*as)[i]->value())) {
...@@ -95,13 +97,17 @@ namespace Sass { ...@@ -95,13 +97,17 @@ namespace Sass {
env->local_frame()[p->name()] = arglist; env->local_frame()[p->name()] = arglist;
Map_Obj argmap = Cast<Map>(a->value()); Map_Obj argmap = Cast<Map>(a->value());
for (auto key : argmap->keys()) { for (auto key : argmap->keys()) {
std::string name = unquote(Cast<String_Constant>(key)->value()); if (String_Constant_Obj str = Cast<String_Constant>(key)) {
arglist->append(SASS_MEMORY_NEW(Argument, std::string param = unquote(str->value());
key->pstate(), arglist->append(SASS_MEMORY_NEW(Argument,
argmap->at(key), key->pstate(),
"$" + name, argmap->at(key),
false, "$" + param,
false)); false,
false));
} else {
throw Exception::InvalidVarKwdType(key->pstate(), key->inspect(), a);
}
} }
} else { } else {
...@@ -131,8 +137,8 @@ namespace Sass { ...@@ -131,8 +137,8 @@ namespace Sass {
if (List_Obj rest = Cast<List>(a->value())) { if (List_Obj rest = Cast<List>(a->value())) {
arglist->separator(rest->separator()); arglist->separator(rest->separator());
for (size_t i = 0, L = rest->size(); i < L; ++i) { for (size_t i = 0, L = rest->length(); i < L; ++i) {
Expression_Obj obj = rest->at(i); Expression_Obj obj = rest->value_at_index(i);
arglist->append(SASS_MEMORY_NEW(Argument, arglist->append(SASS_MEMORY_NEW(Argument,
obj->pstate(), obj->pstate(),
obj, obj,
...@@ -167,8 +173,15 @@ namespace Sass { ...@@ -167,8 +173,15 @@ namespace Sass {
else if (a->is_rest_argument()) { else if (a->is_rest_argument()) {
// normal param and rest arg // normal param and rest arg
List_Obj arglist = Cast<List>(a->value()); List_Obj arglist = Cast<List>(a->value());
if (!arglist) {
if (Expression_Obj arg = Cast<Expression>(a->value())) {
arglist = SASS_MEMORY_NEW(List, a->pstate(), 1);
arglist->append(arg);
}
}
// empty rest arg - treat all args as default values // empty rest arg - treat all args as default values
if (!arglist->length()) { if (!arglist || !arglist->length()) {
break; break;
} else { } else {
if (arglist->length() > LP - ip && !ps->has_rest_parameter()) { if (arglist->length() > LP - ip && !ps->has_rest_parameter()) {
...@@ -205,14 +218,16 @@ namespace Sass { ...@@ -205,14 +218,16 @@ namespace Sass {
Map_Obj argmap = Cast<Map>(a->value()); Map_Obj argmap = Cast<Map>(a->value());
for (auto key : argmap->keys()) { for (auto key : argmap->keys()) {
std::string name = "$" + unquote(Cast<String_Constant>(key)->value()); String_Constant_Ptr val = Cast<String_Constant>(key);
if (val == NULL) throw Exception::InvalidVarKwdType(key->pstate(), key->inspect(), a);
std::string param = "$" + unquote(val->value());
if (!param_map.count(name)) { if (!param_map.count(param)) {
std::stringstream msg; std::stringstream msg;
msg << callee << " has no parameter named " << name; msg << callee << " has no parameter named " << param;
error(msg.str(), a->pstate()); error(msg.str(), a->pstate());
} }
env->local_frame()[name] = argmap->at(key); env->local_frame()[param] = argmap->at(key);
} }
++ia; ++ia;
continue; continue;
...@@ -234,15 +249,21 @@ namespace Sass { ...@@ -234,15 +249,21 @@ namespace Sass {
else { else {
// named arg -- bind it to the appropriately named param // named arg -- bind it to the appropriately named param
if (!param_map.count(a->name())) { if (!param_map.count(a->name())) {
std::stringstream msg; if (ps->has_rest_parameter()) {
msg << callee << " has no parameter named " << a->name(); varargs->append(a);
error(msg.str(), a->pstate()); } else {
std::stringstream msg;
msg << callee << " has no parameter named " << a->name();
error(msg.str(), a->pstate());
}
} }
if (param_map[a->name()]->is_rest_parameter()) { if (param_map[a->name()]) {
std::stringstream msg; if (param_map[a->name()]->is_rest_parameter()) {
msg << "argument " << a->name() << " of " << callee std::stringstream msg;
<< "cannot be used as named argument"; msg << "argument " << a->name() << " of " << callee
error(msg.str(), a->pstate()); << "cannot be used as named argument";
error(msg.str(), a->pstate());
}
} }
if (env->has_local(a->name())) { if (env->has_local(a->name())) {
std::stringstream msg; std::stringstream msg;
...@@ -265,11 +286,7 @@ namespace Sass { ...@@ -265,11 +286,7 @@ namespace Sass {
// cerr << "********" << endl; // cerr << "********" << endl;
if (!env->has_local(leftover->name())) { if (!env->has_local(leftover->name())) {
if (leftover->is_rest_parameter()) { if (leftover->is_rest_parameter()) {
env->local_frame()[leftover->name()] = SASS_MEMORY_NEW(List, env->local_frame()[leftover->name()] = varargs;
leftover->pstate(),
0,
SASS_COMMA,
true);
} }
else if (leftover->default_value()) { else if (leftover->default_value()) {
Expression_Ptr dv = leftover->default_value()->perform(eval); Expression_Ptr dv = leftover->default_value()->perform(eval);
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
...@@ -46,6 +46,9 @@ int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, ...@@ -46,6 +46,9 @@ int base64_encode_block(const char* plaintext_in, int length_in, char* code_out,
result = (fragment & 0x0fc) >> 2; result = (fragment & 0x0fc) >> 2;
*codechar++ = base64_encode_value(result); *codechar++ = base64_encode_value(result);
result = (fragment & 0x003) << 4; result = (fragment & 0x003) << 4;
#ifndef _MSC_VER
__attribute__ ((fallthrough));
#endif
case step_B: case step_B:
if (plainchar == plaintextend) if (plainchar == plaintextend)
{ {
...@@ -57,6 +60,9 @@ int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, ...@@ -57,6 +60,9 @@ int base64_encode_block(const char* plaintext_in, int length_in, char* code_out,
result |= (fragment & 0x0f0) >> 4; result |= (fragment & 0x0f0) >> 4;
*codechar++ = base64_encode_value(result); *codechar++ = base64_encode_value(result);
result = (fragment & 0x00f) << 2; result = (fragment & 0x00f) << 2;
#ifndef _MSC_VER
__attribute__ ((fallthrough));
#endif
case step_C: case step_C:
if (plainchar == plaintextend) if (plainchar == plaintextend)
{ {
......
...@@ -40,7 +40,13 @@ namespace Sass { ...@@ -40,7 +40,13 @@ namespace Sass {
} }
At_Root_Block_Ptr ar = Cast<At_Root_Block>(parent); At_Root_Block_Ptr ar = Cast<At_Root_Block>(parent);
Statement_Ptr ret = this->visit_children(ar->block()); Block_Ptr ret = ar->block();
if (ret != NULL) {
for (auto n : ret->elements()) {
n->perform(this);
}
}
this->parent = old_parent; this->parent = old_parent;
this->parents = old_parents; this->parents = old_parents;
...@@ -97,6 +103,19 @@ namespace Sass { ...@@ -97,6 +103,19 @@ namespace Sass {
return n; return n;
} }
Statement_Ptr CheckNesting::operator()(If_Ptr i)
{
this->visit_children(i);
if (Block_Ptr b = Cast<Block>(i->alternative())) {
for (auto n : i->alternative()->elements()) {
n->perform(this);
}
}
return i;
}
Statement_Ptr CheckNesting::fallback_impl(Statement_Ptr s) Statement_Ptr CheckNesting::fallback_impl(Statement_Ptr s)
{ {
Block_Ptr b1 = Cast<Block>(s); Block_Ptr b1 = Cast<Block>(s);
......
...@@ -22,6 +22,7 @@ namespace Sass { ...@@ -22,6 +22,7 @@ namespace Sass {
Statement_Ptr operator()(Block_Ptr); Statement_Ptr operator()(Block_Ptr);
Statement_Ptr operator()(Definition_Ptr); Statement_Ptr operator()(Definition_Ptr);
Statement_Ptr operator()(If_Ptr);
template <typename U> template <typename U>
Statement_Ptr fallback(U x) { Statement_Ptr fallback(U x) {
......
...@@ -607,16 +607,20 @@ namespace Sass { ...@@ -607,16 +607,20 @@ namespace Sass {
Color_Ptr_Const name_to_color(const char* key) Color_Ptr_Const name_to_color(const char* key)
{ {
auto p = names_to_colors.find(key); return name_to_color(std::string(key));
if (p != names_to_colors.end()) {
return p->second;
}
return 0;
} }
Color_Ptr_Const name_to_color(const std::string& key) Color_Ptr_Const name_to_color(const std::string& key)
{ {
return name_to_color(key.c_str()); // case insensitive lookup. See #2462
std::string lower{key};
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
auto p = names_to_colors.find(lower.c_str());
if (p != names_to_colors.end()) {
return p->second;
}
return 0;
} }
const char* color_to_name(const int key) const char* color_to_name(const int key)
......
File mode changed from 100755 to 100644
...@@ -79,11 +79,12 @@ namespace Sass { ...@@ -79,11 +79,12 @@ namespace Sass {
extern const char supports_kwd[] = "@supports"; extern const char supports_kwd[] = "@supports";
extern const char keyframes_kwd[] = "keyframes"; extern const char keyframes_kwd[] = "keyframes";
extern const char only_kwd[] = "only"; extern const char only_kwd[] = "only";
extern const char rgb_kwd[] = "rgb("; extern const char rgb_fn_kwd[] = "rgb(";
extern const char url_fn_kwd[] = "url(";
extern const char url_kwd[] = "url"; extern const char url_kwd[] = "url";
// extern const char url_prefix_kwd[] = "url-prefix("; // extern const char url_prefix_fn_kwd[] = "url-prefix(";
extern const char important_kwd[] = "important"; extern const char important_kwd[] = "important";
extern const char pseudo_not_kwd[] = ":not("; extern const char pseudo_not_fn_kwd[] = ":not(";
extern const char even_kwd[] = "even"; extern const char even_kwd[] = "even";
extern const char odd_kwd[] = "odd"; extern const char odd_kwd[] = "odd";
extern const char progid_kwd[] = "progid"; extern const char progid_kwd[] = "progid";
......
...@@ -79,11 +79,12 @@ namespace Sass { ...@@ -79,11 +79,12 @@ namespace Sass {
extern const char supports_kwd[]; extern const char supports_kwd[];
extern const char keyframes_kwd[]; extern const char keyframes_kwd[];
extern const char only_kwd[]; extern const char only_kwd[];
extern const char rgb_kwd[]; extern const char rgb_fn_kwd[];
extern const char url_fn_kwd[];
extern const char url_kwd[]; extern const char url_kwd[];
// extern const char url_prefix_kwd[]; // extern const char url_prefix_fn_kwd[];
extern const char important_kwd[]; extern const char important_kwd[];
extern const char pseudo_not_kwd[]; extern const char pseudo_not_fn_kwd[];
extern const char even_kwd[]; extern const char even_kwd[];
extern const char odd_kwd[]; extern const char odd_kwd[];
extern const char progid_kwd[]; extern const char progid_kwd[];
......
...@@ -67,11 +67,14 @@ namespace Sass { ...@@ -67,11 +67,14 @@ namespace Sass {
plugins(), plugins(),
emitter(c_options), emitter(c_options),
ast_gc(),
strings(), strings(),
resources(), resources(),
sheets(), sheets(),
subset_map(), subset_map(),
import_stack(), import_stack(),
callee_stack(),
c_compiler(NULL),
c_headers (std::vector<Sass_Importer_Entry>()), c_headers (std::vector<Sass_Importer_Entry>()),
c_importers (std::vector<Sass_Importer_Entry>()), c_importers (std::vector<Sass_Importer_Entry>()),
...@@ -130,7 +133,7 @@ namespace Sass { ...@@ -130,7 +133,7 @@ namespace Sass {
Context::~Context() Context::~Context()
{ {
// resources were allocated by strdup or malloc // resources were allocated by malloc
for (size_t i = 0; i < resources.size(); ++i) { for (size_t i = 0; i < resources.size(); ++i) {
free(resources[i].contents); free(resources[i].contents);
free(resources[i].srcmap); free(resources[i].srcmap);
...@@ -416,12 +419,12 @@ namespace Sass { ...@@ -416,12 +419,12 @@ namespace Sass {
// need one correct import // need one correct import
bool has_import = false; bool has_import = false;
// process all custom importers (or custom headers) // process all custom importers (or custom headers)
for (Sass_Importer_Entry& importer : importers) { for (Sass_Importer_Entry& importer_ent : importers) {
// int priority = sass_importer_get_priority(importer); // int priority = sass_importer_get_priority(importer);
Sass_Importer_Fn fn = sass_importer_get_function(importer); Sass_Importer_Fn fn = sass_importer_get_function(importer_ent);
// skip importer if it returns NULL // skip importer if it returns NULL
if (Sass_Import_List includes = if (Sass_Import_List includes =
fn(load_path.c_str(), importer, c_compiler) fn(load_path.c_str(), importer_ent, c_compiler)
) { ) {
// get c pointer copy to iterate over // get c pointer copy to iterate over
Sass_Import_List it_includes = includes; Sass_Import_List it_includes = includes;
...@@ -436,15 +439,15 @@ namespace Sass { ...@@ -436,15 +439,15 @@ namespace Sass {
// create the importer struct // create the importer struct
Importer importer(uniq_path, ctx_path); Importer importer(uniq_path, ctx_path);
// query data from the current include // query data from the current include
Sass_Import_Entry include = *it_includes; Sass_Import_Entry include_ent = *it_includes;
char* source = sass_import_take_source(include); char* source = sass_import_take_source(include_ent);
char* srcmap = sass_import_take_srcmap(include); char* srcmap = sass_import_take_srcmap(include_ent);
size_t line = sass_import_get_error_line(include); size_t line = sass_import_get_error_line(include_ent);
size_t column = sass_import_get_error_column(include); size_t column = sass_import_get_error_column(include_ent);
const char *abs_path = sass_import_get_abs_path(include); const char *abs_path = sass_import_get_abs_path(include_ent);
// handle error message passed back from custom importer // handle error message passed back from custom importer
// it may (or may not) override the line and column info // it may (or may not) override the line and column info
if (const char* err_message = sass_import_get_error_message(include)) { if (const char* err_message = sass_import_get_error_message(include_ent)) {
if (source || srcmap) register_resource({ importer, uniq_path }, { source, srcmap }, &pstate); if (source || srcmap) register_resource({ importer, uniq_path }, { source, srcmap }, &pstate);
if (line == std::string::npos && column == std::string::npos) error(err_message, pstate); if (line == std::string::npos && column == std::string::npos) error(err_message, pstate);
else error(err_message, ParserState(ctx_path, source, Position(line, column))); else error(err_message, ParserState(ctx_path, source, Position(line, column)));
...@@ -661,7 +664,8 @@ namespace Sass { ...@@ -661,7 +664,8 @@ namespace Sass {
// should we extend something? // should we extend something?
if (!subset_map.empty()) { if (!subset_map.empty()) {
// create crtp visitor object // create crtp visitor object
Extend extend(*this, subset_map); Extend extend(subset_map);
extend.setEval(expand.eval);
// extend tree nodes // extend tree nodes
extend(root); extend(root);
} }
...@@ -696,10 +700,8 @@ namespace Sass { ...@@ -696,10 +700,8 @@ namespace Sass {
char* Context::render_srcmap() char* Context::render_srcmap()
{ {
if (source_map_file == "") return 0; if (source_map_file == "") return 0;
char* result = 0;
std::string map = emitter.render_srcmap(*this); std::string map = emitter.render_srcmap(*this);
result = sass_copy_c_string(map.c_str()); return sass_copy_c_string(map.c_str());
return result;
} }
...@@ -831,6 +833,8 @@ namespace Sass { ...@@ -831,6 +833,8 @@ namespace Sass {
register_function(ctx, mixin_exists_sig, mixin_exists, env); register_function(ctx, mixin_exists_sig, mixin_exists, env);
register_function(ctx, feature_exists_sig, feature_exists, env); register_function(ctx, feature_exists_sig, feature_exists, env);
register_function(ctx, call_sig, call, env); register_function(ctx, call_sig, call, env);
register_function(ctx, content_exists_sig, content_exists, env);
register_function(ctx, get_function_sig, get_function, env);
// Boolean Functions // Boolean Functions
register_function(ctx, not_sig, sass_not, env); register_function(ctx, not_sig, sass_not, env);
register_function(ctx, if_sig, sass_if, env); register_function(ctx, if_sig, sass_if, env);
......
...@@ -43,6 +43,9 @@ namespace Sass { ...@@ -43,6 +43,9 @@ namespace Sass {
Plugins plugins; Plugins plugins;
Output emitter; Output emitter;
// generic ast node garbage container
// used to avoid possible circular refs
std::vector<AST_Node_Obj> ast_gc;
// resources add under our control // resources add under our control
// these are guaranteed to be freed // these are guaranteed to be freed
std::vector<char*> strings; std::vector<char*> strings;
......
...@@ -23,12 +23,12 @@ namespace Sass { ...@@ -23,12 +23,12 @@ namespace Sass {
Block_Ptr Cssize::operator()(Block_Ptr b) Block_Ptr Cssize::operator()(Block_Ptr b)
{ {
Block_Ptr bb = SASS_MEMORY_NEW(Block, b->pstate(), b->length(), b->is_root()); Block_Obj bb = SASS_MEMORY_NEW(Block, b->pstate(), b->length(), b->is_root());
// bb->tabs(b->tabs()); // bb->tabs(b->tabs());
block_stack.push_back(bb); block_stack.push_back(bb);
append_block(b, bb); append_block(b, bb);
block_stack.pop_back(); block_stack.pop_back();
return bb; return bb.detach();
} }
Statement_Ptr Cssize::operator()(Trace_Ptr t) Statement_Ptr Cssize::operator()(Trace_Ptr t)
...@@ -54,7 +54,8 @@ namespace Sass { ...@@ -54,7 +54,8 @@ namespace Sass {
d->pstate(), d->pstate(),
property, property,
d->value(), d->value(),
d->is_important()); d->is_important(),
d->is_custom_property());
dd->is_indented(d->is_indented()); dd->is_indented(d->is_indented());
dd->tabs(d->tabs()); dd->tabs(d->tabs());
...@@ -174,9 +175,9 @@ namespace Sass { ...@@ -174,9 +175,9 @@ namespace Sass {
if (props->length()) if (props->length())
{ {
Block_Obj bb = SASS_MEMORY_NEW(Block, rr->block()->pstate()); Block_Obj pb = SASS_MEMORY_NEW(Block, rr->block()->pstate());
bb->concat(props); pb->concat(props);
rr->block(bb); rr->block(pb);
for (size_t i = 0, L = rules->length(); i < L; i++) for (size_t i = 0, L = rules->length(); i < L; i++)
{ {
...@@ -259,7 +260,7 @@ namespace Sass { ...@@ -259,7 +260,7 @@ namespace Sass {
tmp |= m->exclude_node(s); tmp |= m->exclude_node(s);
} }
if (!tmp) if (!tmp && m->block())
{ {
Block_Ptr bb = operator()(m->block()); Block_Ptr bb = operator()(m->block());
for (size_t i = 0, L = bb->length(); i < L; ++i) { for (size_t i = 0, L = bb->length(); i < L; ++i) {
...@@ -302,14 +303,17 @@ namespace Sass { ...@@ -302,14 +303,17 @@ namespace Sass {
Statement_Ptr Cssize::bubble(At_Root_Block_Ptr m) Statement_Ptr Cssize::bubble(At_Root_Block_Ptr m)
{ {
if (!m || !m->block()) return NULL;
Block_Ptr bb = SASS_MEMORY_NEW(Block, this->parent()->pstate()); Block_Ptr bb = SASS_MEMORY_NEW(Block, this->parent()->pstate());
Has_Block_Obj new_rule = Cast<Has_Block>(SASS_MEMORY_COPY(this->parent())); Has_Block_Obj new_rule = Cast<Has_Block>(SASS_MEMORY_COPY(this->parent()));
new_rule->block(bb);
new_rule->tabs(this->parent()->tabs());
new_rule->block()->concat(m->block());
Block_Ptr wrapper_block = SASS_MEMORY_NEW(Block, m->block()->pstate()); Block_Ptr wrapper_block = SASS_MEMORY_NEW(Block, m->block()->pstate());
wrapper_block->append(new_rule); if (new_rule) {
new_rule->block(bb);
new_rule->tabs(this->parent()->tabs());
new_rule->block()->concat(m->block());
wrapper_block->append(new_rule);
}
At_Root_Block_Ptr mm = SASS_MEMORY_NEW(At_Root_Block, At_Root_Block_Ptr mm = SASS_MEMORY_NEW(At_Root_Block,
m->pstate(), m->pstate(),
wrapper_block, wrapper_block,
...@@ -442,7 +446,7 @@ namespace Sass { ...@@ -442,7 +446,7 @@ namespace Sass {
for (size_t j = 0, K = slice->length(); j < K; ++j) for (size_t j = 0, K = slice->length(); j < K; ++j)
{ {
Statement_Ptr ss = NULL; Statement_Ptr ss;
Statement_Obj stm = slice->at(j); Statement_Obj stm = slice->at(j);
// this has to go now here (too bad) // this has to go now here (too bad)
Bubble_Obj node = Cast<Bubble>(stm); Bubble_Obj node = Cast<Bubble>(stm);
...@@ -476,8 +480,6 @@ namespace Sass { ...@@ -476,8 +480,6 @@ namespace Sass {
ss->tabs(ss->tabs() + node->tabs()); ss->tabs(ss->tabs() + node->tabs());
ss->group_end(node->group_end()); ss->group_end(node->group_end());
if (!ss) continue;
Block_Obj bb = SASS_MEMORY_NEW(Block, Block_Obj bb = SASS_MEMORY_NEW(Block,
children->pstate(), children->pstate(),
children->length(), children->length(),
...@@ -584,10 +586,11 @@ namespace Sass { ...@@ -584,10 +586,11 @@ namespace Sass {
} }
Media_Query_Ptr mm = SASS_MEMORY_NEW(Media_Query, Media_Query_Ptr mm = SASS_MEMORY_NEW(Media_Query,
mq1->pstate(),
mq1->pstate(), 0, 0,
mq1->length() + mq2->length(), mod == "not", mod == "only" mq1->length() + mq2->length(),
); mod == "not",
mod == "only");
if (!type.empty()) { if (!type.empty()) {
mm->media_type(SASS_MEMORY_NEW(String_Quoted, mq1->pstate(), type)); mm->media_type(SASS_MEMORY_NEW(String_Quoted, mq1->pstate(), type));
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
...@@ -103,7 +103,7 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) ...@@ -103,7 +103,7 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env)
std::cerr << (selector->has_line_break() ? " [line-break]": " -"); std::cerr << (selector->has_line_break() ? " [line-break]": " -");
std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); std::cerr << (selector->has_line_feed() ? " [line-feed]": " -");
std::cerr << std::endl; std::cerr << std::endl;
debug_ast(selector->schema(), "#{} "); debug_ast(selector->schema(), ind + "#{} ");
for(const Complex_Selector_Obj& i : selector->elements()) { debug_ast(i, ind + " ", env); } for(const Complex_Selector_Obj& i : selector->elements()) { debug_ast(i, ind + " ", env); }
...@@ -415,6 +415,7 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) ...@@ -415,6 +415,7 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env)
Declaration_Ptr block = Cast<Declaration>(node); Declaration_Ptr block = Cast<Declaration>(node);
std::cerr << ind << "Declaration " << block; std::cerr << ind << "Declaration " << block;
std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " (" << pstate_source_position(node) << ")";
std::cerr << " [is_custom_property: " << block->is_custom_property() << "] ";
std::cerr << " " << block->tabs() << std::endl; std::cerr << " " << block->tabs() << std::endl;
debug_ast(block->property(), ind + " prop: ", env); debug_ast(block->property(), ind + " prop: ", env);
debug_ast(block->value(), ind + " value: ", env); debug_ast(block->value(), ind + " value: ", env);
...@@ -488,18 +489,6 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) ...@@ -488,18 +489,6 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env)
std::cerr << (block->is_invisible() ? " [INVISIBLE]" : ""); std::cerr << (block->is_invisible() ? " [INVISIBLE]" : "");
std::cerr << " [indent: " << block->tabs() << "]" << std::endl; std::cerr << " [indent: " << block->tabs() << "]" << std::endl;
for(const Statement_Obj& i : block->elements()) { debug_ast(i, ind + " ", env); } for(const Statement_Obj& i : block->elements()) { debug_ast(i, ind + " ", env); }
} else if (Cast<Textual>(node)) {
Textual_Ptr expression = Cast<Textual>(node);
std::cerr << ind << "Textual " << expression;
std::cerr << " (" << pstate_source_position(node) << ")";
if (expression->type() == Textual::NUMBER) std::cerr << " [NUMBER]";
else if (expression->type() == Textual::PERCENTAGE) std::cerr << " [PERCENTAGE]";
else if (expression->type() == Textual::DIMENSION) std::cerr << " [DIMENSION]";
else if (expression->type() == Textual::HEX) std::cerr << " [HEX]";
std::cerr << " [" << expression->value() << "]";
std::cerr << " [interpolant: " << expression->is_interpolant() << "] ";
if (expression->is_delayed()) std::cerr << " [delayed]";
std::cerr << std::endl;
} else if (Cast<Variable>(node)) { } else if (Cast<Variable>(node)) {
Variable_Ptr expression = Cast<Variable>(node); Variable_Ptr expression = Cast<Variable>(node);
std::cerr << ind << "Variable " << expression; std::cerr << ind << "Variable " << expression;
...@@ -524,8 +513,17 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) ...@@ -524,8 +513,17 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env)
std::cerr << " [" << expression->name() << "]"; std::cerr << " [" << expression->name() << "]";
if (expression->is_delayed()) std::cerr << " [delayed]"; if (expression->is_delayed()) std::cerr << " [delayed]";
if (expression->is_interpolant()) std::cerr << " [interpolant]"; if (expression->is_interpolant()) std::cerr << " [interpolant]";
if (expression->is_css()) std::cerr << " [css]";
std::cerr << std::endl; std::cerr << std::endl;
debug_ast(expression->arguments(), ind + " args: ", env); debug_ast(expression->arguments(), ind + " args: ", env);
debug_ast(expression->func(), ind + " func: ", env);
} else if (Cast<Function>(node)) {
Function_Ptr expression = Cast<Function>(node);
std::cerr << ind << "Function " << expression;
std::cerr << " (" << pstate_source_position(node) << ")";
if (expression->is_css()) std::cerr << " [css]";
std::cerr << std::endl;
debug_ast(expression->definition(), ind + " definition: ", env);
} else if (Cast<Arguments>(node)) { } else if (Cast<Arguments>(node)) {
Arguments_Ptr expression = Cast<Arguments>(node); Arguments_Ptr expression = Cast<Arguments>(node);
std::cerr << ind << "Arguments " << expression; std::cerr << ind << "Arguments " << expression;
...@@ -698,6 +696,8 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) ...@@ -698,6 +696,8 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env)
case Expression::Concrete_Type::C_ERROR: std::cerr << " [C_ERROR]"; break; case Expression::Concrete_Type::C_ERROR: std::cerr << " [C_ERROR]"; break;
case Expression::Concrete_Type::FUNCTION: std::cerr << " [FUNCTION]"; break; case Expression::Concrete_Type::FUNCTION: std::cerr << " [FUNCTION]"; break;
case Expression::Concrete_Type::NUM_TYPES: std::cerr << " [NUM_TYPES]"; break; case Expression::Concrete_Type::NUM_TYPES: std::cerr << " [NUM_TYPES]"; break;
case Expression::Concrete_Type::VARIABLE: std::cerr << " [VARIABLE]"; break;
case Expression::Concrete_Type::FUNCTION_VAL: std::cerr << " [FUNCTION_VAL]"; break;
} }
std::cerr << std::endl; std::cerr << std::endl;
} else if (Cast<Has_Block>(node)) { } else if (Cast<Has_Block>(node)) {
......
...@@ -14,7 +14,9 @@ namespace Sass { ...@@ -14,7 +14,9 @@ namespace Sass {
scheduled_space(0), scheduled_space(0),
scheduled_linefeed(0), scheduled_linefeed(0),
scheduled_delimiter(false), scheduled_delimiter(false),
scheduled_crutch(0),
scheduled_mapping(0), scheduled_mapping(0),
in_custom_property(false),
in_comment(false), in_comment(false),
in_wrapped(false), in_wrapped(false),
in_media_block(false), in_media_block(false),
...@@ -101,10 +103,30 @@ namespace Sass { ...@@ -101,10 +103,30 @@ namespace Sass {
// prepend some text or token to the buffer // prepend some text or token to the buffer
void Emitter::prepend_string(const std::string& text) void Emitter::prepend_string(const std::string& text)
{ {
wbuf.smap.prepend(Offset(text)); // do not adjust mappings for utf8 bom
// seems they are not counted in any UA
if (text.compare("\xEF\xBB\xBF") != 0) {
wbuf.smap.prepend(Offset(text));
}
wbuf.buffer = text + wbuf.buffer; wbuf.buffer = text + wbuf.buffer;
} }
char Emitter::last_char()
{
return wbuf.buffer.back();
}
// append a single char to the buffer
void Emitter::append_char(const char chr)
{
// write space/lf
flush_schedules();
// add to buffer
wbuf.buffer += chr;
// account for data in source-maps
wbuf.smap.append(Offset(chr));
}
// append some text or token to the buffer // append some text or token to the buffer
void Emitter::append_string(const std::string& text) void Emitter::append_string(const std::string& text)
{ {
...@@ -145,9 +167,9 @@ namespace Sass { ...@@ -145,9 +167,9 @@ namespace Sass {
add_open_mapping(node); add_open_mapping(node);
// hotfix for browser issues // hotfix for browser issues
// this is pretty ugly indeed // this is pretty ugly indeed
if (scheduled_mapping) { if (scheduled_crutch) {
add_open_mapping(scheduled_mapping); add_open_mapping(scheduled_crutch);
scheduled_mapping = 0; scheduled_crutch = 0;
} }
append_string(text); append_string(text);
add_close_mapping(node); add_close_mapping(node);
...@@ -193,7 +215,7 @@ namespace Sass { ...@@ -193,7 +215,7 @@ namespace Sass {
{ {
scheduled_space = 0; scheduled_space = 0;
append_string(":"); append_string(":");
append_optional_space(); if (!in_custom_property) append_optional_space();
} }
void Emitter::append_mandatory_space() void Emitter::append_mandatory_space()
...@@ -206,7 +228,9 @@ namespace Sass { ...@@ -206,7 +228,9 @@ namespace Sass {
if ((output_style() != COMPRESSED) && buffer().size()) { if ((output_style() != COMPRESSED) && buffer().size()) {
unsigned char lst = buffer().at(buffer().length() - 1); unsigned char lst = buffer().at(buffer().length() - 1);
if (!isspace(lst) || scheduled_delimiter) { if (!isspace(lst) || scheduled_delimiter) {
append_mandatory_space(); if (last_char() != '(') {
append_mandatory_space();
}
} }
} }
} }
......
...@@ -37,9 +37,12 @@ namespace Sass { ...@@ -37,9 +37,12 @@ namespace Sass {
size_t scheduled_space; size_t scheduled_space;
size_t scheduled_linefeed; size_t scheduled_linefeed;
bool scheduled_delimiter; bool scheduled_delimiter;
AST_Node_Ptr scheduled_crutch;
AST_Node_Ptr scheduled_mapping; AST_Node_Ptr scheduled_mapping;
public: public:
// output strings different in custom css properties
bool in_custom_property;
// output strings different in comments // output strings different in comments
bool in_comment; bool in_comment;
// selector list does not get linefeeds // selector list does not get linefeeds
...@@ -66,11 +69,15 @@ namespace Sass { ...@@ -66,11 +69,15 @@ namespace Sass {
void prepend_output(const OutputBuffer& out); void prepend_output(const OutputBuffer& out);
// append some text or token to the buffer // append some text or token to the buffer
void append_string(const std::string& text); void append_string(const std::string& text);
// append a single character to buffer
void append_char(const char chr);
// append some white-space only text // append some white-space only text
void append_wspace(const std::string& text); void append_wspace(const std::string& text);
// append some text or token to the buffer // append some text or token to the buffer
// this adds source-mappings for node start and end // this adds source-mappings for node start and end
void append_token(const std::string& text, const AST_Node_Ptr node); void append_token(const std::string& text, const AST_Node_Ptr node);
// query last appended character
char last_char();
public: // syntax sugar public: // syntax sugar
void append_indentation(); void append_indentation();
......
...@@ -6,17 +6,17 @@ namespace Sass { ...@@ -6,17 +6,17 @@ namespace Sass {
template <typename T> template <typename T>
Environment<T>::Environment(bool is_shadow) Environment<T>::Environment(bool is_shadow)
: local_frame_(std::map<std::string, T>()), : local_frame_(environment_map<std::string, T>()),
parent_(0), is_shadow_(false) parent_(0), is_shadow_(false)
{ } { }
template <typename T> template <typename T>
Environment<T>::Environment(Environment<T>* env, bool is_shadow) Environment<T>::Environment(Environment<T>* env, bool is_shadow)
: local_frame_(std::map<std::string, T>()), : local_frame_(environment_map<std::string, T>()),
parent_(env), is_shadow_(is_shadow) parent_(env), is_shadow_(is_shadow)
{ } { }
template <typename T> template <typename T>
Environment<T>::Environment(Environment<T>& env, bool is_shadow) Environment<T>::Environment(Environment<T>& env, bool is_shadow)
: local_frame_(std::map<std::string, T>()), : local_frame_(environment_map<std::string, T>()),
parent_(&env), is_shadow_(is_shadow) parent_(&env), is_shadow_(is_shadow)
{ } { }
...@@ -45,7 +45,7 @@ namespace Sass { ...@@ -45,7 +45,7 @@ namespace Sass {
} }
template <typename T> template <typename T>
std::map<std::string, T>& Environment<T>::local_frame() { environment_map<std::string, T>& Environment<T>::local_frame() {
return local_frame_; return local_frame_;
} }
...@@ -53,12 +53,25 @@ namespace Sass { ...@@ -53,12 +53,25 @@ namespace Sass {
bool Environment<T>::has_local(const std::string& key) const bool Environment<T>::has_local(const std::string& key) const
{ return local_frame_.find(key) != local_frame_.end(); } { return local_frame_.find(key) != local_frame_.end(); }
template <typename T> EnvResult
Environment<T>::find_local(const std::string& key)
{
auto end = local_frame_.end();
auto it = local_frame_.find(key);
return EnvResult(it, it != end);
}
template <typename T> template <typename T>
T& Environment<T>::get_local(const std::string& key) T& Environment<T>::get_local(const std::string& key)
{ return local_frame_[key]; } { return local_frame_[key]; }
template <typename T> template <typename T>
void Environment<T>::set_local(const std::string& key, T val) void Environment<T>::set_local(const std::string& key, const T& val)
{
local_frame_[key] = val;
}
template <typename T>
void Environment<T>::set_local(const std::string& key, T&& val)
{ {
local_frame_[key] = val; local_frame_[key] = val;
} }
...@@ -86,7 +99,12 @@ namespace Sass { ...@@ -86,7 +99,12 @@ namespace Sass {
{ return (*global_env())[key]; } { return (*global_env())[key]; }
template <typename T> template <typename T>
void Environment<T>::set_global(const std::string& key, T val) void Environment<T>::set_global(const std::string& key, const T& val)
{
global_env()->local_frame_[key] = val;
}
template <typename T>
void Environment<T>::set_global(const std::string& key, T&& val)
{ {
global_env()->local_frame_[key] = val; global_env()->local_frame_[key] = val;
} }
...@@ -126,12 +144,31 @@ namespace Sass { ...@@ -126,12 +144,31 @@ namespace Sass {
// either update already existing lexical value // either update already existing lexical value
// or if flag is set, we create one if no lexical found // or if flag is set, we create one if no lexical found
template <typename T> template <typename T>
void Environment<T>::set_lexical(const std::string& key, T val) void Environment<T>::set_lexical(const std::string& key, const T& val)
{ {
auto cur = this; bool shadow = false; Environment<T>* cur = this;
while (cur->is_lexical() || shadow) { bool shadow = false;
if (cur->has_local(key)) { while ((cur && cur->is_lexical()) || shadow) {
cur->set_local(key, val); EnvResult rv(cur->find_local(key));
if (rv.found) {
rv.it->second = val;
return;
}
shadow = cur->is_shadow();
cur = cur->parent_;
}
set_local(key, val);
}
// this one moves the value
template <typename T>
void Environment<T>::set_lexical(const std::string& key, T&& val)
{
Environment<T>* cur = this;
bool shadow = false;
while ((cur && cur->is_lexical()) || shadow) {
EnvResult rv(cur->find_local(key));
if (rv.found) {
rv.it->second = val;
return; return;
} }
shadow = cur->is_shadow(); shadow = cur->is_shadow();
...@@ -155,6 +192,20 @@ namespace Sass { ...@@ -155,6 +192,20 @@ namespace Sass {
return false; return false;
} }
// look on the full stack for key
// include all scopes available
template <typename T> EnvResult
Environment<T>::find(const std::string& key)
{
auto cur = this;
while (true) {
EnvResult rv(cur->find_local(key));
if (rv.found) return rv;
cur = cur->parent_;
if (!cur) return rv;
}
};
// use array access for getter and setter functions // use array access for getter and setter functions
template <typename T> template <typename T>
T& Environment<T>::operator[](const std::string& key) T& Environment<T>::operator[](const std::string& key)
...@@ -168,7 +219,7 @@ namespace Sass { ...@@ -168,7 +219,7 @@ namespace Sass {
} }
return get_local(key); return get_local(key);
} }
/*
#ifdef DEBUG #ifdef DEBUG
template <typename T> template <typename T>
size_t Environment<T>::print(std::string prefix) size_t Environment<T>::print(std::string prefix)
...@@ -176,7 +227,7 @@ namespace Sass { ...@@ -176,7 +227,7 @@ namespace Sass {
size_t indent = 0; size_t indent = 0;
if (parent_) indent = parent_->print(prefix) + 1; if (parent_) indent = parent_->print(prefix) + 1;
std::cerr << prefix << std::string(indent, ' ') << "== " << this << std::endl; std::cerr << prefix << std::string(indent, ' ') << "== " << this << std::endl;
for (typename std::map<std::string, T>::iterator i = local_frame_.begin(); i != local_frame_.end(); ++i) { for (typename environment_map<std::string, T>::iterator i = local_frame_.begin(); i != local_frame_.end(); ++i) {
if (!ends_with(i->first, "[f]") && !ends_with(i->first, "[f]4") && !ends_with(i->first, "[f]2")) { if (!ends_with(i->first, "[f]") && !ends_with(i->first, "[f]4") && !ends_with(i->first, "[f]2")) {
std::cerr << prefix << std::string(indent, ' ') << i->first << " " << i->second; std::cerr << prefix << std::string(indent, ' ') << i->first << " " << i->second;
if (Value_Ptr val = Cast<Value>(i->second)) if (Value_Ptr val = Cast<Value>(i->second))
...@@ -187,7 +238,7 @@ namespace Sass { ...@@ -187,7 +238,7 @@ namespace Sass {
return indent ; return indent ;
} }
#endif #endif
*/
// compile implementation for AST_Node // compile implementation for AST_Node
template class Environment<AST_Node_Obj>; template class Environment<AST_Node_Obj>;
......
...@@ -2,17 +2,26 @@ ...@@ -2,17 +2,26 @@
#define SASS_ENVIRONMENT_H #define SASS_ENVIRONMENT_H
#include <string> #include <string>
#include <map>
#include "ast_fwd_decl.hpp" #include "ast_fwd_decl.hpp"
#include "ast_def_macros.hpp" #include "ast_def_macros.hpp"
namespace Sass { namespace Sass {
typedef environment_map<std::string, AST_Node_Obj>::iterator EnvIter;
class EnvResult {
public:
EnvIter it;
bool found;
public:
EnvResult(EnvIter it, bool found)
: it(it), found(found) {}
};
template <typename T> template <typename T>
class Environment { class Environment {
// TODO: test with map // TODO: test with map
std::map<std::string, T> local_frame_; environment_map<std::string, T> local_frame_;
ADD_PROPERTY(Environment*, parent) ADD_PROPERTY(Environment*, parent)
ADD_PROPERTY(bool, is_shadow) ADD_PROPERTY(bool, is_shadow)
...@@ -37,14 +46,17 @@ namespace Sass { ...@@ -37,14 +46,17 @@ namespace Sass {
// scope operates on the current frame // scope operates on the current frame
std::map<std::string, T>& local_frame(); environment_map<std::string, T>& local_frame();
bool has_local(const std::string& key) const; bool has_local(const std::string& key) const;
EnvResult find_local(const std::string& key);
T& get_local(const std::string& key); T& get_local(const std::string& key);
// set variable on the current frame // set variable on the current frame
void set_local(const std::string& key, T val); void set_local(const std::string& key, const T& val);
void set_local(const std::string& key, T&& val);
void del_local(const std::string& key); void del_local(const std::string& key);
...@@ -60,7 +72,8 @@ namespace Sass { ...@@ -60,7 +72,8 @@ namespace Sass {
T& get_global(const std::string& key); T& get_global(const std::string& key);
// set a variable on the global frame // set a variable on the global frame
void set_global(const std::string& key, T val); void set_global(const std::string& key, const T& val);
void set_global(const std::string& key, T&& val);
void del_global(const std::string& key); void del_global(const std::string& key);
...@@ -72,12 +85,17 @@ namespace Sass { ...@@ -72,12 +85,17 @@ namespace Sass {
// see if we have a lexical we could update // see if we have a lexical we could update
// either update already existing lexical value // either update already existing lexical value
// or we create a new one on the current frame // or we create a new one on the current frame
void set_lexical(const std::string& key, T val); void set_lexical(const std::string& key, T&& val);
void set_lexical(const std::string& key, const T& val);
// look on the full stack for key // look on the full stack for key
// include all scopes available // include all scopes available
bool has(const std::string& key) const; bool has(const std::string& key) const;
// look on the full stack for key
// include all scopes available
EnvResult find(const std::string& key);
// use array access for getter and setter functions // use array access for getter and setter functions
T& operator[](const std::string& key); T& operator[](const std::string& key);
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment