├── src ├── test │ ├── resources │ │ ├── sass │ │ │ ├── error.sass │ │ │ ├── inc │ │ │ │ └── mixins.sass │ │ │ ├── src │ │ │ │ └── include.sass │ │ │ ├── compressed │ │ │ │ ├── output-without-map.css │ │ │ │ └── output-with-map.css │ │ │ ├── test │ │ │ │ └── functions.sass │ │ │ ├── nested │ │ │ │ ├── output-without-map.css │ │ │ │ └── output-with-map.css │ │ │ └── input.sass │ │ ├── scss │ │ │ ├── error.scss │ │ │ ├── inc │ │ │ │ └── mixins.scss │ │ │ ├── src │ │ │ │ └── include.scss │ │ │ ├── compressed │ │ │ │ ├── output-without-map.css │ │ │ │ └── output-with-map.css │ │ │ ├── test │ │ │ │ └── functions.scss │ │ │ ├── nested │ │ │ │ ├── output-without-map.css │ │ │ │ └── output-with-map.css │ │ │ └── input.scss │ │ ├── linux-x64 │ │ │ └── libjsass_test.so │ │ ├── windows-x64 │ │ │ └── libjsass_test.dll │ │ ├── linux-aarch64 │ │ │ └── libjsass_test.so │ │ ├── linux-armhf32 │ │ │ └── libjsass_test.so │ │ ├── darwin-aarch64 │ │ │ └── libjsass_test.dylib │ │ └── darwin-x86_64 │ │ │ └── libjsass_test.dylib │ ├── java │ │ └── io │ │ │ └── bit3 │ │ │ └── jsass │ │ │ ├── Utils.java │ │ │ ├── adapter │ │ │ ├── NativeAdapterTest.java │ │ │ ├── NativeTestAdapter.java │ │ │ └── NativeTestLoader.java │ │ │ ├── Sass2ScssTest.java │ │ │ ├── AbstractCompileTest.java │ │ │ ├── TestImporter.java │ │ │ ├── ExceptionTest.java │ │ │ ├── PrecisionTest.java │ │ │ └── TestFunctions.java │ └── c │ │ └── CMakeLists.txt └── main │ ├── c │ ├── version_script.map │ ├── exported_symbols_list.txt │ ├── Toolchain-mingw64-amd64.cmake │ ├── Toolchain-linux-aarch64.cmake │ ├── Toolchain-linux-armhf32.cmake │ ├── Toolchain-darwin-amd64.cmake │ ├── Toolchain-darwin-aarch64.cmake │ ├── io_bit3_jsass_adapter_NativeAdapter.h │ └── CMakeLists.txt │ ├── java │ └── io │ │ └── bit3 │ │ └── jsass │ │ ├── type │ │ ├── SassValue.java │ │ ├── SassNull.java │ │ ├── SassError.java │ │ ├── SassWarning.java │ │ ├── SassBoolean.java │ │ ├── SassMap.java │ │ └── SassNumber.java │ │ ├── adapter │ │ ├── NativeContext.java │ │ ├── NativeFileContext.java │ │ ├── LoaderException.java │ │ ├── NativeStringContext.java │ │ ├── AbstractNativeContext.java │ │ ├── NativeOptions.java │ │ └── NativeImport.java │ │ ├── importer │ │ ├── Importer.java │ │ ├── ImportException.java │ │ └── JsassCustomHeaderImporter.java │ │ ├── Separator.java │ │ ├── function │ │ ├── arguments │ │ │ ├── converter │ │ │ │ ├── ConversionException.java │ │ │ │ ├── ArgumentConverter.java │ │ │ │ ├── ContextArgumentConverter.java │ │ │ │ ├── LastImportArgumentConverter.java │ │ │ │ ├── StringArgumentConverter.java │ │ │ │ ├── ByteArgumentConverter.java │ │ │ │ ├── LongArgumentConverter.java │ │ │ │ ├── FloatArgumentConverter.java │ │ │ │ ├── ShortArgumentConverter.java │ │ │ │ ├── IntegerArgumentConverter.java │ │ │ │ ├── CharacterArgumentConverter.java │ │ │ │ ├── DoubleArgumentConverter.java │ │ │ │ ├── BooleanArgumentConverter.java │ │ │ │ └── ObjectArgumentConverter.java │ │ │ └── factory │ │ │ │ ├── ArgumentConverterFactory.java │ │ │ │ ├── StringArgumentConverterFactory.java │ │ │ │ ├── ByteArgumentConverterFactory.java │ │ │ │ ├── LongArgumentConverterFactory.java │ │ │ │ ├── FloatArgumentConverterFactory.java │ │ │ │ ├── ShortArgumentConverterFactory.java │ │ │ │ ├── DoubleArgumentConverterFactory.java │ │ │ │ ├── BooleanArgumentConverterFactory.java │ │ │ │ ├── IntegerArgumentConverterFactory.java │ │ │ │ ├── CharacterArgumentConverterFactory.java │ │ │ │ ├── ContextArgumentConverterFactory.java │ │ │ │ └── LastImportArgumentConverterFactory.java │ │ ├── FunctionArgumentSignature.java │ │ ├── JsassCustomFunctions.java │ │ └── FunctionWrapper.java │ │ ├── Sass2ScssOptions.java │ │ ├── annotation │ │ ├── DebugFunction.java │ │ ├── ErrorFunction.java │ │ ├── WarnFunction.java │ │ ├── DefaultByteValue.java │ │ ├── DefaultFloatValue.java │ │ ├── DefaultLongValue.java │ │ ├── DefaultShortValue.java │ │ ├── DefaultBooleanValue.java │ │ ├── DefaultDoubleValue.java │ │ ├── DefaultIntegerValue.java │ │ ├── DefaultStringValue.java │ │ ├── DefaultCharacterValue.java │ │ └── Name.java │ │ ├── OutputStyle.java │ │ ├── context │ │ ├── Context.java │ │ ├── FileContext.java │ │ ├── StringContext.java │ │ ├── ImportStack.java │ │ └── AbstractContext.java │ │ ├── UnsupportedContextException.java │ │ ├── Output.java │ │ ├── package-info.java │ │ └── CompilationException.java │ └── resources │ ├── linux-x64 │ └── libjsass.so │ ├── windows-x64 │ ├── libjsass.dll │ └── libsass.dll │ ├── linux-aarch64 │ └── libjsass.so │ ├── linux-armhf32 │ └── libjsass.so │ ├── darwin-aarch64 │ └── libjsass.dylib │ └── darwin-x86_64 │ └── libjsass.dylib ├── .gitmodules ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .scrutinizer.yml ├── settings.gradle ├── .gitattributes ├── CMakeLists.txt ├── bin ├── run-ci-tests.sh ├── make-libjsass-linux-x64.sh ├── make-libjsass-windows-x64.sh ├── make-libjsass-darwin.sh ├── make-libjsass-linux-x64-local.sh ├── make-libjsass-linux-armhf32-local.sh └── update-test-assets.sh ├── gradle-ci.properties ├── example └── webapp │ ├── src │ └── main │ │ └── webapp │ │ └── WEB-INF │ │ ├── assets │ │ ├── foundation │ │ │ ├── components │ │ │ │ ├── _menu-icon.scss │ │ │ │ ├── _float.scss │ │ │ │ ├── _sticky.scss │ │ │ │ ├── _flex.scss │ │ │ │ ├── _accordion-menu.scss │ │ │ │ ├── _badge.scss │ │ │ │ ├── _label.scss │ │ │ │ ├── _thumbnail.scss │ │ │ │ ├── _dropdown.scss │ │ │ │ ├── _progress-bar.scss │ │ │ │ ├── _flex-video.scss │ │ │ │ ├── _close-button.scss │ │ │ │ ├── _title-bar.scss │ │ │ │ ├── _drilldown.scss │ │ │ │ ├── _breadcrumbs.scss │ │ │ │ └── _callout.scss │ │ │ ├── util │ │ │ │ ├── _util.scss │ │ │ │ ├── _selector.scss │ │ │ │ ├── _flex.scss │ │ │ │ └── _color.scss │ │ │ ├── typography │ │ │ │ ├── _alignment.scss │ │ │ │ ├── _typography.scss │ │ │ │ ├── _helpers.scss │ │ │ │ └── _print.scss │ │ │ ├── grid │ │ │ │ ├── _size.scss │ │ │ │ ├── _gutter.scss │ │ │ │ ├── _layout.scss │ │ │ │ ├── _grid.scss │ │ │ │ ├── _position.scss │ │ │ │ └── _row.scss │ │ │ └── forms │ │ │ │ ├── _help-text.scss │ │ │ │ ├── _forms.scss │ │ │ │ ├── _checkbox.scss │ │ │ │ ├── _label.scss │ │ │ │ ├── _fieldset.scss │ │ │ │ ├── _select.scss │ │ │ │ ├── _progress.scss │ │ │ │ ├── _error.scss │ │ │ │ └── _meter.scss │ │ └── motion-ui │ │ │ ├── util │ │ │ ├── _unit.scss │ │ │ ├── _animation.scss │ │ │ ├── _args.scss │ │ │ ├── _selector.scss │ │ │ ├── _transition.scss │ │ │ └── _series.scss │ │ │ ├── effects │ │ │ ├── _zoom.scss │ │ │ ├── _wiggle.scss │ │ │ ├── _shake.scss │ │ │ ├── _fade.scss │ │ │ ├── _spin.scss │ │ │ ├── _slide.scss │ │ │ └── _hinge.scss │ │ │ ├── motion-ui.scss │ │ │ ├── transitions │ │ │ ├── _fade.scss │ │ │ ├── _zoom.scss │ │ │ ├── _spin.scss │ │ │ ├── _slide.scss │ │ │ └── _hinge.scss │ │ │ └── _settings.scss │ │ ├── web.xml │ │ └── scss │ │ └── app.scss │ └── build.gradle ├── CONTRIBUTING.md ├── gradle.properties ├── .drone.yml ├── LICENSE ├── README.md └── .gitignore /src/test/resources/sass/error.sass: -------------------------------------------------------------------------------- 1 | @error "Test exception" 2 | -------------------------------------------------------------------------------- /src/test/resources/scss/error.scss: -------------------------------------------------------------------------------- 1 | @error "Test exception"; 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libsass"] 2 | path = src/main/libsass 3 | url = https://github.com/sass/libsass.git 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit3/jsass/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/c/version_script.map: -------------------------------------------------------------------------------- 1 | { 2 | global: 3 | Java_io_bit3_jsass_adapter_*; 4 | local: 5 | *; 6 | }; 7 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/type/SassValue.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.type; 2 | 3 | public interface SassValue { 4 | } 5 | -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | checks: 2 | java: true 3 | 4 | build: 5 | environment: 6 | sdkman: 7 | - java@11.0.2-open 8 | -------------------------------------------------------------------------------- /src/main/resources/linux-x64/libjsass.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit3/jsass/HEAD/src/main/resources/linux-x64/libjsass.so -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/adapter/NativeContext.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.adapter; 2 | 3 | interface NativeContext { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/resources/windows-x64/libjsass.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit3/jsass/HEAD/src/main/resources/windows-x64/libjsass.dll -------------------------------------------------------------------------------- /src/main/resources/windows-x64/libsass.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit3/jsass/HEAD/src/main/resources/windows-x64/libsass.dll -------------------------------------------------------------------------------- /src/main/resources/linux-aarch64/libjsass.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit3/jsass/HEAD/src/main/resources/linux-aarch64/libjsass.so -------------------------------------------------------------------------------- /src/main/resources/linux-armhf32/libjsass.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit3/jsass/HEAD/src/main/resources/linux-armhf32/libjsass.so -------------------------------------------------------------------------------- /src/test/resources/linux-x64/libjsass_test.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit3/jsass/HEAD/src/test/resources/linux-x64/libjsass_test.so -------------------------------------------------------------------------------- /src/main/c/exported_symbols_list.txt: -------------------------------------------------------------------------------- 1 | # This file is for resolving global symbol conflict in Mac OS. 2 | 3 | _Java_io_bit3_jsass_adapter_* 4 | -------------------------------------------------------------------------------- /src/main/resources/darwin-aarch64/libjsass.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit3/jsass/HEAD/src/main/resources/darwin-aarch64/libjsass.dylib -------------------------------------------------------------------------------- /src/main/resources/darwin-x86_64/libjsass.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit3/jsass/HEAD/src/main/resources/darwin-x86_64/libjsass.dylib -------------------------------------------------------------------------------- /src/test/resources/windows-x64/libjsass_test.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit3/jsass/HEAD/src/test/resources/windows-x64/libjsass_test.dll -------------------------------------------------------------------------------- /src/test/resources/linux-aarch64/libjsass_test.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit3/jsass/HEAD/src/test/resources/linux-aarch64/libjsass_test.so -------------------------------------------------------------------------------- /src/test/resources/linux-armhf32/libjsass_test.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit3/jsass/HEAD/src/test/resources/linux-armhf32/libjsass_test.so -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' 3 | } 4 | 5 | rootProject.name = 'jsass' 6 | -------------------------------------------------------------------------------- /src/test/resources/darwin-aarch64/libjsass_test.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit3/jsass/HEAD/src/test/resources/darwin-aarch64/libjsass_test.dylib -------------------------------------------------------------------------------- /src/test/resources/darwin-x86_64/libjsass_test.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit3/jsass/HEAD/src/test/resources/darwin-x86_64/libjsass_test.dylib -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | .gitignore text eol=lf diff=word 2 | 3 | # LF line ending is necessary to run tests successfully 4 | *.scss text eol=lf 5 | *.sass text eol=lf 6 | *.css text eol=lf 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.2) 2 | project(jsass) 3 | 4 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 5 | 6 | set(SOURCE_FILES main.cpp) 7 | add_executable(jsass ${SOURCE_FILES}) -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/importer/Importer.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.importer; 2 | 3 | import java.util.Collection; 4 | 5 | @FunctionalInterface 6 | public interface Importer { 7 | Collection apply(String url, Import previous); 8 | } 9 | -------------------------------------------------------------------------------- /bin/run-ci-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | if [[ -d .gradle ]]; then 6 | rm -rf .gradle 7 | fi 8 | 9 | mkdir -p .gradle_home 10 | 11 | ./gradlew --info --full-stacktrace --gradle-user-home "$PWD/.gradle_home" clean test "$@" 12 | -------------------------------------------------------------------------------- /src/test/resources/sass/inc/mixins.sass: -------------------------------------------------------------------------------- 1 | // This file is included through include path 2 | 3 | =link($color, $hover) 4 | &, 5 | &:link, 6 | &:visited 7 | color: $color 8 | 9 | &:hover, 10 | &:focus, 11 | &:active 12 | color: $hover 13 | -------------------------------------------------------------------------------- /gradle-ci.properties: -------------------------------------------------------------------------------- 1 | org.gradle.logging.level=info 2 | org.gradle.logging.stacktrace=full 3 | org.gradle.parallel=true 4 | org.gradle.caching=true 5 | org.gradle.jvmargs=-Xmx8096M 6 | org.gradle.java.installations.paths=/opt/java8,/opt/java11,/opt/java17,/opt/java21 7 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/Separator.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass; 2 | 3 | public enum Separator { 4 | COMMA(','), 5 | SPACE(' '); 6 | 7 | public final char character; 8 | 9 | Separator(char character) { 10 | this.character = character; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/type/SassNull.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.type; 2 | 3 | public class SassNull implements SassValue { 4 | public static final int TYPE = 1; 5 | 6 | public static final SassNull SINGLETON = new SassNull(); 7 | 8 | private SassNull() { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/test/resources/scss/inc/mixins.scss: -------------------------------------------------------------------------------- 1 | // This file is included through include path 2 | 3 | @mixin link($color, $hover) { 4 | &, 5 | &:link, 6 | &:visited { 7 | color: $color; 8 | } 9 | 10 | &:hover, 11 | &:focus, 12 | &:active { 13 | color: $hover; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/adapter/NativeFileContext.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.adapter; 2 | 3 | class NativeFileContext extends AbstractNativeContext { 4 | protected NativeFileContext(String inputPath, String outputPath, NativeOptions options) { 5 | super(inputPath, outputPath, options); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/components/_menu-icon.scss: -------------------------------------------------------------------------------- 1 | @mixin foundation-menu-icon { 2 | .menu-icon { 3 | @include hamburger($color: $titlebar-icon-color, $color-hover: $titlebar-icon-color-hover); 4 | } 5 | 6 | .menu-icon.dark { 7 | @include hamburger; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/test/resources/sass/src/include.sass: -------------------------------------------------------------------------------- 1 | // Special behavior: 2 | // * when compiling before testing (update-test-assets.sh), this file is included through include path. 3 | // * when compiling in junit, this file is included through custom importer. 4 | 5 | .include 6 | content: "I'm imported by a custom importer!" 7 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/adapter/LoaderException.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.adapter; 2 | 3 | public class LoaderException extends RuntimeException { 4 | private static final long serialVersionUID = -5441356515637315401L; 5 | 6 | public LoaderException(Throwable cause) { 7 | super(cause); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/importer/ImportException.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.importer; 2 | 3 | public class ImportException extends RuntimeException { 4 | private static final long serialVersionUID = -8956412938684506348L; 5 | 6 | public ImportException(Throwable cause) { 7 | super(cause); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/test/resources/scss/src/include.scss: -------------------------------------------------------------------------------- 1 | // Special behavior: 2 | // * when compiling before testing (update-test-assets.sh), this file is included through include path. 3 | // * when compiling in junit, this file is included through custom importer. 4 | 5 | .include { 6 | content: "I'm imported by a custom importer!"; 7 | } 8 | -------------------------------------------------------------------------------- /src/test/java/io/bit3/jsass/Utils.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass; 2 | 3 | public class Utils { 4 | private Utils() { 5 | throw new UnsupportedOperationException(); 6 | } 7 | 8 | public static String dos2unix(String string) { 9 | return null == string ? null : string.replace("\r", ""); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ============ 3 | 4 | If you'd like to contribute, please respect the following rules: 5 | 6 | - use Googles code style 7 | - do not produce PMD violations 8 | - if possible, provide a unit test 9 | - run `./gradlew clean check` to validate locally 10 | - PRs with failing build will not be merged! 11 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/util/_util.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | @import 'unit'; 6 | @import 'value'; 7 | @import 'color'; 8 | @import 'selector'; 9 | @import 'flex'; 10 | @import 'breakpoint'; 11 | @import 'mixins'; 12 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/util/_unit.scss: -------------------------------------------------------------------------------- 1 | /// Removes the unit (e.g. px, em, rem) from a value, returning the number only. 2 | /// @param {Number} $num - Number to strip unit from. 3 | /// @return {Number} The same number, sans unit. 4 | /// @access private 5 | @function strip-unit($num) { 6 | @return $num / ($num * 0 + 1); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/converter/ConversionException.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.converter; 2 | 3 | public class ConversionException extends RuntimeException { 4 | private static final long serialVersionUID = -6339937166526234394L; 5 | 6 | public ConversionException(String message) { 7 | super(message); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/type/SassError.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.type; 2 | 3 | public class SassError implements SassValue { 4 | public static final int TYPE = 8; 5 | 6 | private final String message; 7 | 8 | public SassError(String message) { 9 | this.message = message; 10 | } 11 | 12 | public String getMessage() { 13 | return message; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/type/SassWarning.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.type; 2 | 3 | public class SassWarning implements SassValue { 4 | public static final int TYPE = 9; 5 | 6 | private final String message; 7 | 8 | public SassWarning(String message) { 9 | this.message = message; 10 | } 11 | 12 | public String getMessage() { 13 | return message; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | version=5.11.2-SNAPSHOT 2 | 3 | systemProp.sonar.host.url=https://sonarhub.io 4 | systemProp.sonar.links.homepage=http://jsass.rtfd.org 5 | systemProp.sonar.links.ci=https://travis-ci.org/bit3/jsass 6 | systemProp.sonar.links.issue=https://gitlab.com/jsass/jsass/issues 7 | systemProp.sonar.links.scm=https://gitlab.com/jsass/jsass.git 8 | systemProp.sonar.links.scm_dev=git@gitlab.com:jsass/jsass.git 9 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/Sass2ScssOptions.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass; 2 | 3 | public class Sass2ScssOptions { 4 | public static int PRETTIFY0 = 0; 5 | public static int PRETTIFY1 = 1; 6 | public static int PRETTIFY2 = 2; 7 | public static int PRETTIFY3 = 3; 8 | 9 | public static int KEEP_COMMENT = 32; 10 | public static int STRIP_COMMENT = 64; 11 | public static int CONVERT_COMMENT = 128; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/adapter/NativeStringContext.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.adapter; 2 | 3 | class NativeStringContext extends AbstractNativeContext { 4 | public final String source; 5 | 6 | protected NativeStringContext( 7 | String source, String inputPath, String outputPath, NativeOptions options 8 | ) { 9 | super(inputPath, outputPath, options); 10 | this.source = source; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/resources/sass/compressed/output-without-map.css: -------------------------------------------------------------------------------- 1 | .include{content:"I'm imported by a custom importer!"}.unit-test{display:block}.unit-test .compile{font-size:16px}.unit-test .world{content:"Hello world"}.unit-test .globe{content:"Hello globe"}.unit-test .increment{z-index:11}.unit-test .increment-five{z-index:15}.unit-test .decrement{z-index:9}.unit-test .decrement-five{z-index:5}.unit-test .operatory{padding-top:calc(.5rem + 1px)} 2 | -------------------------------------------------------------------------------- /src/test/resources/scss/compressed/output-without-map.css: -------------------------------------------------------------------------------- 1 | .include{content:"I'm imported by a custom importer!"}.unit-test{display:block}.unit-test .compile{font-size:16px}.unit-test .world{content:"Hello world"}.unit-test .globe{content:"Hello globe"}.unit-test .increment{z-index:11}.unit-test .increment-five{z-index:15}.unit-test .decrement{z-index:9}.unit-test .decrement-five{z-index:5}.unit-test .operatory{padding-top:calc(.5rem + 1px)} 2 | -------------------------------------------------------------------------------- /bin/make-libjsass-linux-x64.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | if [[ -z "$(which docker)" ]]; then 6 | echo "The linux build require docker" 7 | exit 1 8 | fi 9 | 10 | if [[ -z "$(which gradle)" ]]; then 11 | echo "The linux build require gradle" 12 | exit 1 13 | fi 14 | 15 | DIR=$(dirname $(dirname $(realpath "$0"))) 16 | cd "$DIR" 17 | 18 | # Compile binaries 19 | ./gradlew -g /tmp buildNativeLinux64Libs 20 | -------------------------------------------------------------------------------- /bin/make-libjsass-windows-x64.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | if [[ -z "$(which docker)" ]]; then 6 | echo "The windows build require docker" 7 | exit 1 8 | fi 9 | 10 | if [[ -z "$(which gradle)" ]]; then 11 | echo "The linux build require gradle" 12 | exit 1 13 | fi 14 | 15 | DIR=$(dirname $(dirname $(realpath "$0"))) 16 | cd "$DIR" 17 | 18 | # Compile binaries 19 | ./gradlew -g /tmp buildNativeWindows64Libs 20 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/annotation/DebugFunction.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ElementType.METHOD}) 10 | /** 11 | * Declare this method as @error function. 12 | */ 13 | public @interface DebugFunction { 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/annotation/ErrorFunction.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ElementType.METHOD}) 10 | /** 11 | * Declare this method as @error function. 12 | */ 13 | public @interface ErrorFunction { 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/annotation/WarnFunction.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ElementType.METHOD}) 10 | /** 11 | * Declare this method as @warn function. 12 | */ 13 | public @interface WarnFunction { 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/type/SassBoolean.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.type; 2 | 3 | public class SassBoolean implements SassValue { 4 | public static final int TYPE = 4; 5 | 6 | private boolean value; 7 | 8 | public SassBoolean(boolean value) { 9 | this.value = value; 10 | } 11 | 12 | public boolean getValue() { 13 | return value; 14 | } 15 | 16 | public void setValue(boolean value) { 17 | this.value = value; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/util/_animation.scss: -------------------------------------------------------------------------------- 1 | /// Creates a keyframe from one or more effect functions and assigns it to the element by adding the `animation-name` property. 2 | /// @param {Function} $effects... - One or more effect functions to build the keyframe with. 3 | @mixin mui-animation($args...) { 4 | $name: map-get(-mui-process-args($args...), name); 5 | @include mui-keyframes($name, $args...); 6 | animation-name: unquote($name); 7 | } 8 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/util/_args.scss: -------------------------------------------------------------------------------- 1 | /// Processes a series of keyframe function arguments. 2 | /// @access private 3 | @function -mui-process-args($args...) { 4 | @if length($args) == 1 { 5 | $arg: nth($args, 1); 6 | 7 | @if type-of($arg) == 'string' { 8 | @return call($arg); 9 | } @else if type-of($arg) == 'map' { 10 | @return $arg; 11 | } 12 | } 13 | 14 | @return -mui-keyframe-combine($args...); 15 | } 16 | -------------------------------------------------------------------------------- /src/test/resources/sass/compressed/output-with-map.css: -------------------------------------------------------------------------------- 1 | .include{content:"I'm imported by a custom importer!"}.unit-test{display:block}.unit-test .compile{font-size:16px}.unit-test .world{content:"Hello world"}.unit-test .globe{content:"Hello globe"}.unit-test .increment{z-index:11}.unit-test .increment-five{z-index:15}.unit-test .decrement{z-index:9}.unit-test .decrement-five{z-index:5}.unit-test .operatory{padding-top:calc(.5rem + 1px)} 2 | 3 | /*# sourceMappingURL=output-with-map.css.map */ -------------------------------------------------------------------------------- /src/test/resources/scss/compressed/output-with-map.css: -------------------------------------------------------------------------------- 1 | .include{content:"I'm imported by a custom importer!"}.unit-test{display:block}.unit-test .compile{font-size:16px}.unit-test .world{content:"Hello world"}.unit-test .globe{content:"Hello globe"}.unit-test .increment{z-index:11}.unit-test .increment-five{z-index:15}.unit-test .decrement{z-index:9}.unit-test .decrement-five{z-index:5}.unit-test .operatory{padding-top:calc(.5rem + 1px)} 2 | 3 | /*# sourceMappingURL=output-with-map.css.map */ -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/annotation/DefaultByteValue.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ElementType.PARAMETER}) 10 | public @interface DefaultByteValue { 11 | 12 | /** 13 | * The default value. 14 | */ 15 | byte value(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/annotation/DefaultFloatValue.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ElementType.PARAMETER}) 10 | public @interface DefaultFloatValue { 11 | 12 | /** 13 | * The default value. 14 | */ 15 | float value(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/annotation/DefaultLongValue.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ElementType.PARAMETER}) 10 | public @interface DefaultLongValue { 11 | 12 | /** 13 | * The default value. 14 | */ 15 | long value(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/annotation/DefaultShortValue.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ElementType.PARAMETER}) 10 | public @interface DefaultShortValue { 11 | 12 | /** 13 | * The default value. 14 | */ 15 | short value(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/annotation/DefaultBooleanValue.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ElementType.PARAMETER}) 10 | public @interface DefaultBooleanValue { 11 | 12 | /** 13 | * The default value. 14 | */ 15 | boolean value(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/annotation/DefaultDoubleValue.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ElementType.PARAMETER}) 10 | public @interface DefaultDoubleValue { 11 | 12 | /** 13 | * The default value. 14 | */ 15 | double value(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/annotation/DefaultIntegerValue.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ElementType.PARAMETER}) 10 | public @interface DefaultIntegerValue { 11 | 12 | /** 13 | * The default value. 14 | */ 15 | int value(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/annotation/DefaultStringValue.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ElementType.PARAMETER}) 10 | public @interface DefaultStringValue { 11 | 12 | /** 13 | * The default value. 14 | */ 15 | String value(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/factory/ArgumentConverterFactory.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.factory; 2 | 3 | import io.bit3.jsass.function.arguments.converter.ArgumentConverter; 4 | 5 | import java.lang.reflect.Method; 6 | import java.lang.reflect.Parameter; 7 | 8 | public interface ArgumentConverterFactory { 9 | boolean canHandle(Class targetType); 10 | 11 | ArgumentConverter create(Object object, Method method, Parameter parameter); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/annotation/DefaultCharacterValue.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ElementType.PARAMETER}) 10 | public @interface DefaultCharacterValue { 11 | 12 | /** 13 | * The default value. 14 | */ 15 | char value(); 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/io/bit3/jsass/adapter/NativeAdapterTest.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.adapter; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.junit.jupiter.api.Assertions.*; 6 | 7 | class NativeAdapterTest { 8 | 9 | /** 10 | * Ensure the correct libsass version is used. 11 | */ 12 | @Test 13 | void libsassVersion() { 14 | assertEquals( 15 | "3.6.6", 16 | NativeAdapter.libsassVersion() 17 | ); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/adapter/AbstractNativeContext.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.adapter; 2 | 3 | abstract class AbstractNativeContext implements NativeContext { 4 | public final String inputPath; 5 | 6 | public final String outputPath; 7 | 8 | public final NativeOptions options; 9 | 10 | protected AbstractNativeContext(String inputPath, String outputPath, NativeOptions options) { 11 | this.inputPath = inputPath; 12 | this.outputPath = outputPath; 13 | this.options = options; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/resources/sass/test/functions.sass: -------------------------------------------------------------------------------- 1 | // Special behavior: 2 | // * when compiling before testing (update-test-assets.sh), this file is included through include path. 3 | // * when compiling in junit, this file is NOT included (=empty imports). The function are declared as custom functions. 4 | 5 | @function hello($name: 'world') 6 | @return 'Hello ' + $name 7 | 8 | @function increment($value, $increment: 1) 9 | @return $value + $increment 10 | 11 | @function decrement($value, $decrement: 1) 12 | @return $value - $decrement 13 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/annotation/Name.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ElementType.PARAMETER}) 10 | public @interface Name { 11 | 12 | /** 13 | * The parameter name. 14 | * 15 | *

Defines the parameter name used in the sass language for named parameters.

16 | */ 17 | String value(); 18 | } 19 | -------------------------------------------------------------------------------- /src/test/resources/scss/test/functions.scss: -------------------------------------------------------------------------------- 1 | // Special behavior: 2 | // * when compiling before testing (update-test-assets.sh), this file is included through include path. 3 | // * when compiling in junit, this file is NOT included (=empty imports). The function are declared as custom functions. 4 | 5 | @function hello($name: 'world') { 6 | @return 'Hello ' + $name; 7 | } 8 | 9 | @function increment($value, $increment: 1) { 10 | @return $value + $increment; 11 | } 12 | 13 | @function decrement($value, $decrement: 1) { 14 | @return $value - $decrement; 15 | } 16 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/components/_float.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group float 7 | //// 8 | 9 | @mixin foundation-float-classes { 10 | .float-left { 11 | float: left !important; 12 | } 13 | 14 | .float-right { 15 | float: right !important; 16 | } 17 | 18 | .float-center { 19 | display: block; 20 | margin-left: auto; 21 | margin-right: auto; 22 | } 23 | 24 | .clearfix { 25 | @include clearfix; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /example/webapp/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'war' 3 | 4 | group = 'io.bit3' 5 | description = 'jsass webapp example.' 6 | 7 | sourceCompatibility = 1.8 8 | targetCompatibility = 1.8 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | compile group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0' 16 | compile group: 'io.bit3', name: 'jsass', version: '5.3.0' 17 | compile group: 'commons-io', name: 'commons-io', version: '2.5' 18 | compile group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.21' 19 | } 20 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/effects/_zoom.scss: -------------------------------------------------------------------------------- 1 | /// Creates a scaling transition. A scale of `1` means the element is the same size. Larger numbers make the element bigger, while numbers less than 1 make the element smaller. 2 | /// @param {Number} $from [1.5] - Size to start at. 3 | /// @param {Number} $to [1] - Size to end at. 4 | @function zoom( 5 | $from: 0, 6 | $to: 1 7 | ) { 8 | $keyframes: ( 9 | name: 'scale-#{$to}-to-#{$from}', 10 | 0: (transform: scale($from)), 11 | 100: (transform: scale($to)), 12 | ); 13 | 14 | @return $keyframes; 15 | } 16 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/effects/_wiggle.scss: -------------------------------------------------------------------------------- 1 | /// Creates a wiggling animation. 2 | /// @param {Number} $intensity [7deg] - Intensity of the wiggle. Can be any CSS angle unit. 3 | /// @return {Map} A keyframes map that can be used with the `generate-keyframes()` mixin. 4 | @function wiggle($intensity: 7deg) { 5 | $keyframes: ( 6 | name: 'wiggle-#{$intensity}', 7 | (40, 50, 60): (transform: rotate($intensity)), 8 | (35, 45, 55, 65): (transform: rotate(-$intensity)), 9 | (0, 30, 70, 100): (transform: rotate(0)), 10 | ); 11 | 12 | @return $keyframes; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/OutputStyle.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass; 2 | 3 | public enum OutputStyle { 4 | /** 5 | * Nested style. 6 | */ 7 | NESTED(1), 8 | 9 | /** 10 | * Expanded style. 11 | */ 12 | EXPANDED(2), 13 | 14 | /** 15 | * Compact style. 16 | */ 17 | COMPACT(3), 18 | 19 | /** 20 | * Compressed style. 21 | */ 22 | COMPRESSED(4); 23 | 24 | /** 25 | * The numeric representation. 26 | * 27 | *

This is primary used in the native adapter. 28 | */ 29 | public final int numeric; 30 | 31 | OutputStyle(int numeric) { 32 | this.numeric = numeric; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/resources/sass/nested/output-without-map.css: -------------------------------------------------------------------------------- 1 | .include { 2 | content: "I'm imported by a custom importer!"; } 3 | 4 | .unit-test { 5 | display: block; } 6 | .unit-test .compile { 7 | font-size: 16px; } 8 | .unit-test .world { 9 | content: "Hello world"; } 10 | .unit-test .globe { 11 | content: "Hello globe"; } 12 | .unit-test .increment { 13 | z-index: 11; } 14 | .unit-test .increment-five { 15 | z-index: 15; } 16 | .unit-test .decrement { 17 | z-index: 9; } 18 | .unit-test .decrement-five { 19 | z-index: 5; } 20 | .unit-test .operatory { 21 | padding-top: calc(0.5rem + 1px); } 22 | -------------------------------------------------------------------------------- /src/test/resources/scss/nested/output-without-map.css: -------------------------------------------------------------------------------- 1 | .include { 2 | content: "I'm imported by a custom importer!"; } 3 | 4 | .unit-test { 5 | display: block; } 6 | .unit-test .compile { 7 | font-size: 16px; } 8 | .unit-test .world { 9 | content: "Hello world"; } 10 | .unit-test .globe { 11 | content: "Hello globe"; } 12 | .unit-test .increment { 13 | z-index: 11; } 14 | .unit-test .increment-five { 15 | z-index: 15; } 16 | .unit-test .decrement { 17 | z-index: 9; } 18 | .unit-test .decrement-five { 19 | z-index: 5; } 20 | .unit-test .operatory { 21 | padding-top: calc(0.5rem + 1px); } 22 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/effects/_shake.scss: -------------------------------------------------------------------------------- 1 | /// Creates a shaking animation. 2 | /// @param {Percentage} $intensity [7%] - Intensity of the shake, as a percentage value. 3 | /// @return {Map} A keyframes map that can be used with the `generate-keyframes()` mixin. 4 | @function shake($intensity: 7%) { 5 | $right: (0, 10, 20, 30, 40, 50, 60, 70, 80, 90); 6 | $left: (5, 15, 25, 35, 45, 55, 65, 75, 85, 95); 7 | 8 | $keyframes: ( 9 | name: 'shake-#{($intensity / 1%)}', 10 | $right: (transform: translateX($intensity)), 11 | $left: (transform: translateX(-$intensity)), 12 | ); 13 | 14 | @return $keyframes; 15 | } 16 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | jsassServlet 8 | io.bit3.jsass.example.webapp.JsassServlet 9 | 10 | 11 | jsassServlet 12 | /css/* 13 | 14 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/typography/_alignment.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | @mixin foundation-text-alignment { 6 | @each $size in $breakpoint-classes { 7 | @include breakpoint($size) { 8 | @each $align in (left, right, center, justify) { 9 | @if $size != $-zf-zero-breakpoint { 10 | .#{$size}-text-#{$align} { 11 | text-align: $align; 12 | } 13 | } 14 | @else { 15 | .text-#{$align} { 16 | text-align: $align; 17 | } 18 | } 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/resources/sass/nested/output-with-map.css: -------------------------------------------------------------------------------- 1 | .include { 2 | content: "I'm imported by a custom importer!"; } 3 | 4 | .unit-test { 5 | display: block; } 6 | .unit-test .compile { 7 | font-size: 16px; } 8 | .unit-test .world { 9 | content: "Hello world"; } 10 | .unit-test .globe { 11 | content: "Hello globe"; } 12 | .unit-test .increment { 13 | z-index: 11; } 14 | .unit-test .increment-five { 15 | z-index: 15; } 16 | .unit-test .decrement { 17 | z-index: 9; } 18 | .unit-test .decrement-five { 19 | z-index: 5; } 20 | .unit-test .operatory { 21 | padding-top: calc(0.5rem + 1px); } 22 | 23 | /*# sourceMappingURL=output-with-map.css.map */ -------------------------------------------------------------------------------- /src/test/resources/scss/nested/output-with-map.css: -------------------------------------------------------------------------------- 1 | .include { 2 | content: "I'm imported by a custom importer!"; } 3 | 4 | .unit-test { 5 | display: block; } 6 | .unit-test .compile { 7 | font-size: 16px; } 8 | .unit-test .world { 9 | content: "Hello world"; } 10 | .unit-test .globe { 11 | content: "Hello globe"; } 12 | .unit-test .increment { 13 | z-index: 11; } 14 | .unit-test .increment-five { 15 | z-index: 15; } 16 | .unit-test .decrement { 17 | z-index: 9; } 18 | .unit-test .decrement-five { 19 | z-index: 5; } 20 | .unit-test .operatory { 21 | padding-top: calc(0.5rem + 1px); } 22 | 23 | /*# sourceMappingURL=output-with-map.css.map */ -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/FunctionArgumentSignature.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function; 2 | 3 | public class FunctionArgumentSignature { 4 | 5 | private String name; 6 | private Object defaultValue; 7 | 8 | public FunctionArgumentSignature(String name, Object defaultValue) { 9 | this.name = name; 10 | this.defaultValue = defaultValue; 11 | } 12 | 13 | public String getName() { 14 | return name; 15 | } 16 | 17 | public void setName(String name) { 18 | this.name = name; 19 | } 20 | 21 | public Object getDefaultValue() { 22 | return defaultValue; 23 | } 24 | 25 | public void setDefaultValue(Object defaultValue) { 26 | this.defaultValue = defaultValue; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/c/Toolchain-mingw64-amd64.cmake: -------------------------------------------------------------------------------- 1 | # the name of the target operating system 2 | SET(CMAKE_SYSTEM_NAME Windows) 3 | 4 | # which compilers to use for C and C++ 5 | SET(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) 6 | SET(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) 7 | SET(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) 8 | 9 | # here is the target environment located 10 | SET(CMAKE_FIND_ROOT_PATH /usr/share/mingw-w64) 11 | 12 | # adjust the default behaviour of the FIND_XXX() commands: 13 | # search headers and libraries in the target environment, search 14 | # programs in the host environment 15 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 16 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) 17 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) 18 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/context/Context.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.context; 2 | 3 | import io.bit3.jsass.Options; 4 | 5 | import java.io.Serializable; 6 | import java.net.URI; 7 | 8 | public interface Context extends Serializable { 9 | 10 | /** 11 | * Return the input file path. 12 | * 13 | * @return The input file path or null if no path is specified. 14 | */ 15 | URI getInputPath(); 16 | 17 | /** 18 | * Return the output file path. 19 | * 20 | * @return The output file path or null if no path is specified. 21 | */ 22 | URI getOutputPath(); 23 | 24 | /** 25 | * Return the compiler options. 26 | * 27 | * @return The compiler options. 28 | */ 29 | Options getOptions(); 30 | } 31 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/typography/_typography.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group typography 7 | //// 8 | 9 | // scss-lint:disable DeclarationOrder 10 | 11 | // Base typography styles (tags only) 12 | @import 'base'; 13 | 14 | // Typography helper classes (classes only) 15 | @import 'helpers'; 16 | 17 | // Text alignment classes 18 | @import 'alignment'; 19 | 20 | // Print styles 21 | @import 'print'; 22 | 23 | @mixin foundation-typography { 24 | @include foundation-typography-base; 25 | @include foundation-typography-helpers; 26 | @include foundation-text-alignment; 27 | @include foundation-print-styles; 28 | } 29 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/grid/_size.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group grid 7 | //// 8 | 9 | /// Set the width of a grid column. 10 | /// 11 | /// @param {Number|List} $width [$grid-column-count] - Width to make the column. You can pass in any value accepted by the `grid-column()` function, such as `6`, `50%`, or `1 of 2`. 12 | @mixin grid-column-size( 13 | $columns: $grid-column-count 14 | ) { 15 | width: grid-column($columns); 16 | } 17 | 18 | /// Shorthand for `grid-column-size()`. 19 | /// @alias grid-column-size 20 | @mixin grid-col-size( 21 | $columns: $grid-column-count 22 | ) { 23 | @include grid-column-size($columns); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/factory/StringArgumentConverterFactory.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.factory; 2 | 3 | import io.bit3.jsass.function.arguments.converter.ArgumentConverter; 4 | import io.bit3.jsass.function.arguments.converter.StringArgumentConverter; 5 | 6 | import java.lang.reflect.Method; 7 | import java.lang.reflect.Parameter; 8 | 9 | public class StringArgumentConverterFactory implements ArgumentConverterFactory { 10 | 11 | @Override 12 | public boolean canHandle(Class targetType) { 13 | return String.class.isAssignableFrom(targetType); 14 | } 15 | 16 | @Override 17 | public ArgumentConverter create(Object object, Method method, Parameter parameter) { 18 | return new StringArgumentConverter(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/components/_sticky.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | @mixin foundation-sticky { 6 | .sticky-container { 7 | position: relative; 8 | } 9 | 10 | .sticky { 11 | position: absolute; 12 | z-index: 0; 13 | transform: translate3d(0, 0, 0); 14 | } 15 | 16 | .sticky.is-stuck { 17 | position: fixed; 18 | z-index: 5; 19 | 20 | &.is-at-top { 21 | top: 0; 22 | } 23 | 24 | &.is-at-bottom { 25 | bottom: 0; 26 | } 27 | } 28 | 29 | .sticky.is-anchored { 30 | position: absolute; 31 | left: auto; 32 | right: auto; 33 | 34 | &.is-at-bottom { 35 | bottom: 0; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/motion-ui.scss: -------------------------------------------------------------------------------- 1 | // Motion UI by ZURB 2 | // foundation.zurb.com/motion-ui 3 | // Licensed under MIT Open Source 4 | 5 | @import 'settings'; 6 | 7 | @import 'util/animation'; 8 | @import 'util/args'; 9 | @import 'util/keyframe'; 10 | @import 'util/selector'; 11 | @import 'util/series'; 12 | @import 'util/transition'; 13 | @import 'util/unit'; 14 | 15 | @import 'effects/fade'; 16 | @import 'effects/hinge'; 17 | @import 'effects/spin'; 18 | @import 'effects/zoom'; 19 | @import 'effects/shake'; 20 | @import 'effects/slide'; 21 | @import 'effects/wiggle'; 22 | 23 | @import 'transitions/fade'; 24 | @import 'transitions/hinge'; 25 | @import 'transitions/zoom'; 26 | @import 'transitions/slide'; 27 | @import 'transitions/spin'; 28 | 29 | @import 'classes'; 30 | -------------------------------------------------------------------------------- /src/main/c/Toolchain-linux-aarch64.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # CMake defines to cross-compile to ARM/Linux using glibc. 3 | # 4 | 5 | # the name of the target operating system 6 | SET(CMAKE_SYSTEM_NAME Linux) 7 | 8 | # which compilers to use for C and C++ 9 | SET(CMAKE_C_COMPILER aarch64-linux-gnu-gcc) 10 | SET(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++) 11 | SET(CMAKE_ASM_COMPILER aarch64-linux-gnu-gcc) 12 | SET(CMAKE_SYSTEM_PROCESSOR aarch64) 13 | 14 | ADD_DEFINITIONS("-march=armv8-a -mcpu=generic") 15 | 16 | # rdynamic means the backtrace should work 17 | IF (CMAKE_BUILD_TYPE MATCHES "Debug") 18 | add_definitions(-rdynamic) 19 | ENDIF() 20 | 21 | # avoids annoying and pointless warnings from gcc 22 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -U_FORTIFY_SOURCE") 23 | SET(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -c") 24 | 25 | -------------------------------------------------------------------------------- /src/main/c/Toolchain-linux-armhf32.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # CMake defines to cross-compile to ARM/Linux using glibc. 3 | # 4 | 5 | # the name of the target operating system 6 | SET(CMAKE_SYSTEM_NAME Linux) 7 | 8 | # which compilers to use for C and C++ 9 | SET(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc) 10 | SET(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++) 11 | SET(CMAKE_ASM_COMPILER arm-linux-gnueabihf-gcc) 12 | SET(CMAKE_SYSTEM_PROCESSOR arm) 13 | 14 | #ADD_DEFINITIONS("-march=armv6 -mfloat-abi=hard") 15 | 16 | # rdynamic means the backtrace should work 17 | IF (CMAKE_BUILD_TYPE MATCHES "Debug") 18 | add_definitions(-rdynamic) 19 | ENDIF() 20 | 21 | # avoids annoying and pointless warnings from gcc 22 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -U_FORTIFY_SOURCE") 23 | SET(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -c") 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/factory/ByteArgumentConverterFactory.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.factory; 2 | 3 | import io.bit3.jsass.function.arguments.converter.ArgumentConverter; 4 | import io.bit3.jsass.function.arguments.converter.ByteArgumentConverter; 5 | import io.bit3.jsass.type.TypeUtils; 6 | 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.Parameter; 9 | 10 | public class ByteArgumentConverterFactory implements ArgumentConverterFactory { 11 | 12 | @Override 13 | public boolean canHandle(Class targetType) { 14 | return TypeUtils.isaByte(targetType); 15 | } 16 | 17 | @Override 18 | public ArgumentConverter create(Object object, Method method, Parameter parameter) { 19 | return new ByteArgumentConverter(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/factory/LongArgumentConverterFactory.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.factory; 2 | 3 | import io.bit3.jsass.function.arguments.converter.ArgumentConverter; 4 | import io.bit3.jsass.function.arguments.converter.LongArgumentConverter; 5 | import io.bit3.jsass.type.TypeUtils; 6 | 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.Parameter; 9 | 10 | public class LongArgumentConverterFactory implements ArgumentConverterFactory { 11 | 12 | @Override 13 | public boolean canHandle(Class targetType) { 14 | return TypeUtils.isaLong(targetType); 15 | } 16 | 17 | @Override 18 | public ArgumentConverter create(Object object, Method method, Parameter parameter) { 19 | return new LongArgumentConverter(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/factory/FloatArgumentConverterFactory.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.factory; 2 | 3 | import io.bit3.jsass.function.arguments.converter.ArgumentConverter; 4 | import io.bit3.jsass.function.arguments.converter.FloatArgumentConverter; 5 | import io.bit3.jsass.type.TypeUtils; 6 | 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.Parameter; 9 | 10 | public class FloatArgumentConverterFactory implements ArgumentConverterFactory { 11 | 12 | @Override 13 | public boolean canHandle(Class targetType) { 14 | return TypeUtils.isaFloat(targetType); 15 | } 16 | 17 | @Override 18 | public ArgumentConverter create(Object object, Method method, Parameter parameter) { 19 | return new FloatArgumentConverter(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/factory/ShortArgumentConverterFactory.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.factory; 2 | 3 | import io.bit3.jsass.function.arguments.converter.ArgumentConverter; 4 | import io.bit3.jsass.function.arguments.converter.ShortArgumentConverter; 5 | import io.bit3.jsass.type.TypeUtils; 6 | 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.Parameter; 9 | 10 | public class ShortArgumentConverterFactory implements ArgumentConverterFactory { 11 | 12 | @Override 13 | public boolean canHandle(Class targetType) { 14 | return TypeUtils.isaShort(targetType); 15 | } 16 | 17 | @Override 18 | public ArgumentConverter create(Object object, Method method, Parameter parameter) { 19 | return new ShortArgumentConverter(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/factory/DoubleArgumentConverterFactory.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.factory; 2 | 3 | import io.bit3.jsass.function.arguments.converter.ArgumentConverter; 4 | import io.bit3.jsass.function.arguments.converter.DoubleArgumentConverter; 5 | import io.bit3.jsass.type.TypeUtils; 6 | 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.Parameter; 9 | 10 | public class DoubleArgumentConverterFactory implements ArgumentConverterFactory { 11 | 12 | @Override 13 | public boolean canHandle(Class targetType) { 14 | return TypeUtils.isaDouble(targetType); 15 | } 16 | 17 | @Override 18 | public ArgumentConverter create(Object object, Method method, Parameter parameter) { 19 | return new DoubleArgumentConverter(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/context/FileContext.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.context; 2 | 3 | import io.bit3.jsass.Options; 4 | 5 | import java.net.URI; 6 | 7 | /** 8 | * A context to compile a file from the filesystem. 9 | */ 10 | public class FileContext extends AbstractContext { 11 | private static final long serialVersionUID = -1235536277472179438L; 12 | 13 | /** 14 | * Create a new string context. 15 | * 16 | * @param inputPath The input path to read the file from. 17 | * @param outputPath The output path to write the file to, or null to in-memory 18 | * compilation. 19 | * @param options The compiler options. 20 | */ 21 | public FileContext(URI inputPath, URI outputPath, Options options) { 22 | super(inputPath, outputPath, options); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/factory/BooleanArgumentConverterFactory.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.factory; 2 | 3 | import io.bit3.jsass.function.arguments.converter.ArgumentConverter; 4 | import io.bit3.jsass.function.arguments.converter.BooleanArgumentConverter; 5 | import io.bit3.jsass.type.TypeUtils; 6 | 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.Parameter; 9 | 10 | public class BooleanArgumentConverterFactory implements ArgumentConverterFactory { 11 | 12 | @Override 13 | public boolean canHandle(Class targetType) { 14 | return TypeUtils.isaBoolean(targetType); 15 | } 16 | 17 | @Override 18 | public ArgumentConverter create(Object object, Method method, Parameter parameter) { 19 | return new BooleanArgumentConverter(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/factory/IntegerArgumentConverterFactory.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.factory; 2 | 3 | import io.bit3.jsass.function.arguments.converter.ArgumentConverter; 4 | import io.bit3.jsass.function.arguments.converter.IntegerArgumentConverter; 5 | import io.bit3.jsass.type.TypeUtils; 6 | 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.Parameter; 9 | 10 | public class IntegerArgumentConverterFactory implements ArgumentConverterFactory { 11 | 12 | @Override 13 | public boolean canHandle(Class targetType) { 14 | return TypeUtils.isaInteger(targetType); 15 | } 16 | 17 | @Override 18 | public ArgumentConverter create(Object object, Method method, Parameter parameter) { 19 | return new IntegerArgumentConverter(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/components/_flex.scss: -------------------------------------------------------------------------------- 1 | @mixin foundation-flex-classes { 2 | // Horizontal alignment using justify-content 3 | @each $hdir, $prop in map-remove($-zf-flex-justify, left) { 4 | .align-#{$hdir} { 5 | @include flex-align($x: $hdir); 6 | } 7 | } 8 | 9 | // Vertical alignment using align-items and align-self 10 | @each $vdir, $prop in $-zf-flex-align { 11 | .align-#{$vdir} { 12 | @include flex-align($y: $vdir); 13 | } 14 | 15 | .align-self-#{$vdir} { 16 | @include flex-align-self($y: $vdir); 17 | } 18 | } 19 | 20 | // Source ordering 21 | @include -zf-each-breakpoint { 22 | @for $i from 1 through 6 { 23 | .#{$-zf-size}-order-#{$i} { 24 | @include flex-order($i); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/forms/_help-text.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group forms 7 | //// 8 | 9 | /// Default color for help text. 10 | /// @type Color 11 | $helptext-color: $black !default; 12 | 13 | /// Default font size for help text. 14 | /// @type Number 15 | $helptext-font-size: rem-calc(13) !default; 16 | 17 | /// Default font style for help text. 18 | /// @type Keyword 19 | $helptext-font-style: italic !default; 20 | 21 | @mixin foundation-form-helptext { 22 | .help-text { 23 | $margin-top: ($form-spacing * 0.5) * -1; 24 | 25 | margin-top: $margin-top; 26 | font-size: $helptext-font-size; 27 | font-style: $helptext-font-style; 28 | color: $helptext-color; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/factory/CharacterArgumentConverterFactory.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.factory; 2 | 3 | import io.bit3.jsass.function.arguments.converter.ArgumentConverter; 4 | import io.bit3.jsass.function.arguments.converter.CharacterArgumentConverter; 5 | import io.bit3.jsass.type.TypeUtils; 6 | 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.Parameter; 9 | 10 | public class CharacterArgumentConverterFactory implements ArgumentConverterFactory { 11 | 12 | @Override 13 | public boolean canHandle(Class targetType) { 14 | return TypeUtils.isaCharacter(targetType); 15 | } 16 | 17 | @Override 18 | public ArgumentConverter create(Object object, Method method, Parameter parameter) { 19 | return new CharacterArgumentConverter(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/factory/ContextArgumentConverterFactory.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.factory; 2 | 3 | import io.bit3.jsass.context.Context; 4 | import io.bit3.jsass.function.arguments.converter.ArgumentConverter; 5 | import io.bit3.jsass.function.arguments.converter.ContextArgumentConverter; 6 | 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.Parameter; 9 | 10 | public class ContextArgumentConverterFactory implements ArgumentConverterFactory { 11 | 12 | @Override 13 | public boolean canHandle(Class targetType) { 14 | return Context.class.isAssignableFrom(targetType); 15 | } 16 | 17 | @Override 18 | public ArgumentConverter create(Object object, Method method, Parameter parameter) { 19 | return new ContextArgumentConverter(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/factory/LastImportArgumentConverterFactory.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.factory; 2 | 3 | import io.bit3.jsass.function.arguments.converter.ArgumentConverter; 4 | import io.bit3.jsass.function.arguments.converter.LastImportArgumentConverter; 5 | import io.bit3.jsass.importer.Import; 6 | 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.Parameter; 9 | 10 | public class LastImportArgumentConverterFactory implements ArgumentConverterFactory { 11 | 12 | @Override 13 | public boolean canHandle(Class targetType) { 14 | return Import.class.isAssignableFrom(targetType); 15 | } 16 | 17 | @Override 18 | public ArgumentConverter create(Object object, Method method, Parameter parameter) { 19 | return new LastImportArgumentConverter(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/converter/ArgumentConverter.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.converter; 2 | 3 | import io.bit3.jsass.context.Context; 4 | import io.bit3.jsass.context.ImportStack; 5 | import io.bit3.jsass.function.FunctionArgumentSignature; 6 | import io.bit3.jsass.function.FunctionArgumentSignatureFactory; 7 | 8 | import java.lang.reflect.Method; 9 | import java.lang.reflect.Parameter; 10 | import java.util.List; 11 | 12 | public interface ArgumentConverter { 13 | Object convert( 14 | List remainingArguments, 15 | ImportStack importStack, 16 | Context context 17 | ); 18 | 19 | List argumentSignatures( 20 | Object object, 21 | Method method, 22 | Parameter parameter, 23 | FunctionArgumentSignatureFactory factory 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/effects/_fade.scss: -------------------------------------------------------------------------------- 1 | /// Creates a fading animation. 2 | /// @param {Number} $from [0] - Opacity to start at. 3 | /// @param {Number} $to [1] - Opacity to end at. 4 | /// @return {Map} A keyframes map that can be used with the `generate-keyframes()` mixin. 5 | @function fade( 6 | $from: 0, 7 | $to: 1 8 | ) { 9 | $type: type-of($from); 10 | $keyframes: (); 11 | 12 | @if $type == 'string' { 13 | @if $from == in { 14 | $from: 0; 15 | $to: 1; 16 | } @else if $from == out { 17 | $from: 1; 18 | $to: 0; 19 | } 20 | } 21 | 22 | $fromName: $from * 100; 23 | $toName: $to * 100; 24 | 25 | $keyframes: ( 26 | name: 'fade-#{$fromName}-to-#{$toName}', 27 | 0: (opacity: $from), 28 | 100: (opacity: $to), 29 | ); 30 | 31 | @return $keyframes; 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/UnsupportedContextException.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass; 2 | 3 | import io.bit3.jsass.context.Context; 4 | 5 | public class UnsupportedContextException extends RuntimeException { 6 | private static final long serialVersionUID = -5832354814221827572L; 7 | private final Context context; 8 | 9 | /** 10 | * Construct a new unsupported context exception with the given context. 11 | * 12 | * @param context The unsupported {@link Context} instance. 13 | */ 14 | public UnsupportedContextException(Context context) { 15 | super( 16 | String.format( 17 | "Context type \"%s\" is not supported", 18 | null == context ? "null" : context.getClass().getName() 19 | ) 20 | ); 21 | this.context = context; 22 | } 23 | 24 | public Context getContext() { 25 | return context; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/c/Toolchain-darwin-amd64.cmake: -------------------------------------------------------------------------------- 1 | include(CMakeForceCompiler) 2 | 3 | # the name of the target operating system 4 | SET(CMAKE_SYSTEM_NAME Darwin) 5 | 6 | SET(CMAKE_OSX_SYSROOT /osxcross/SDK/MacOSX13.1.sdk) 7 | 8 | # which compilers to use for C and C++ 9 | SET(CMAKE_C_COMPILER x86_64-apple-darwin22.2-clang) 10 | SET(CMAKE_CXX_COMPILER x86_64-apple-darwin22.2-clang++-libc++) 11 | SET(CMAKE_AR x86_64-apple-darwin22.2-ar CACHE FILEPATH "Archiver") 12 | 13 | # here is the target environment located 14 | SET(CMAKE_FIND_ROOT_PATH /osxcross/SDK/MacOSX13.1.sdk/usr/include) 15 | 16 | # adjust the default behaviour of the FIND_XXX() commands: 17 | # search headers and libraries in the target environment, search 18 | # programs in the host environment 19 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 20 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) 21 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) 22 | -------------------------------------------------------------------------------- /.drone.yml: -------------------------------------------------------------------------------- 1 | kind: pipeline 2 | name: test-arm 3 | 4 | platform: 5 | os: linux 6 | arch: arm 7 | 8 | steps: 9 | - name: build 10 | image: eclipse-temurin:11 11 | failure: ignore 12 | commands: 13 | - mkdir -p /tmp/gradle /tmp/gradle_home /tmp/gradle_build 14 | - ./gradlew --info --full-stacktrace --project-cache-dir /tmp/gradle --gradle-user-home "/tmp/.gradle_home" -Dorg.gradle.project.buildDir=/tmp/gradle_build clean check 15 | 16 | --- 17 | 18 | kind: pipeline 19 | name: test-arm64 20 | 21 | platform: 22 | os: linux 23 | arch: arm64 24 | 25 | steps: 26 | - name: build 27 | image: eclipse-temurin:11 28 | commands: 29 | - mkdir -p /tmp/gradle /tmp/gradle_home /tmp/gradle_build 30 | - ./gradlew --info --full-stacktrace --project-cache-dir /tmp/gradle --gradle-user-home "/tmp/.gradle_home" -Dorg.gradle.project.buildDir=/tmp/gradle_build clean check 31 | -------------------------------------------------------------------------------- /src/main/c/Toolchain-darwin-aarch64.cmake: -------------------------------------------------------------------------------- 1 | include(CMakeForceCompiler) 2 | 3 | # the name of the target operating system 4 | SET(CMAKE_SYSTEM_NAME Darwin) 5 | 6 | SET(CMAKE_OSX_SYSROOT /osxcross/SDK/MacOSX13.1.sdk) 7 | 8 | # which compilers to use for C and C++ 9 | SET(CMAKE_C_COMPILER aarch64-apple-darwin22.2-clang) 10 | SET(CMAKE_CXX_COMPILER aarch64-apple-darwin22.2-clang++-libc++) 11 | SET(CMAKE_AR aarch64-apple-darwin22.2-ar CACHE FILEPATH "Archiver") 12 | 13 | # here is the target environment located 14 | SET(CMAKE_FIND_ROOT_PATH /osxcross/SDK/MacOSX13.1.sdk/usr/include) 15 | 16 | # adjust the default behaviour of the FIND_XXX() commands: 17 | # search headers and libraries in the target environment, search 18 | # programs in the host environment 19 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 20 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) 21 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) 22 | -------------------------------------------------------------------------------- /src/test/resources/sass/input.sass: -------------------------------------------------------------------------------- 1 | // imported through include-path 2 | @import mixins 3 | 4 | // imported through custom importer 5 | @import include 6 | 7 | // custom functions 8 | @import functions 9 | 10 | .unit-test 11 | display: block 12 | 13 | .compile 14 | font-size: 16px 15 | 16 | .world 17 | content: hello() 18 | 19 | .globe 20 | content: hello("globe") 21 | 22 | .increment 23 | z-index: increment(10) 24 | 25 | .increment-five 26 | z-index: increment(10, 5) 27 | 28 | .decrement 29 | z-index: decrement(10) 30 | 31 | .decrement-five 32 | z-index: decrement(10, 5) 33 | 34 | // issue #73 35 | .operatory 36 | $input-padding-y: 0.5rem 37 | $input-border-width: 1px 38 | 39 | padding-top: calc(#{$input-padding-y} + #{$input-border-width}) 40 | 41 | @warn "I'm a warn message" 42 | @error "I'm an error message" 43 | @debug "I'm a debug message" 44 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/effects/_spin.scss: -------------------------------------------------------------------------------- 1 | /// Creates a spinning animation. 2 | /// @param {Keyword} $direction [cw] - Direction to spin. Should be `cw` (clockwise) or `ccw` (counterclockwise). 3 | /// @param {Number} $amount [360deg] - Amount to spin. Can be any CSS angle unit. 4 | /// @return {Map} A keyframes map that can be used with the `generate-keyframes()` mixin. 5 | @function spin( 6 | $state: in, 7 | $direction: cw, 8 | $amount: 1turn 9 | ) { 10 | $start: 0; 11 | $end: 0; 12 | 13 | @if $state == in { 14 | $start: if($direction == ccw, $amount, $amount * -1); 15 | $end: 0; 16 | } @else { 17 | $start: 0; 18 | $end: if($direction == ccw, $amount * -1, $amount); 19 | } 20 | 21 | $keyframes: ( 22 | name: 'spin-#{$direction}-#{$amount}', 23 | 0: (transform: rotate($start)), 24 | 100: (transform: rotate($end)), 25 | ); 26 | 27 | @return $keyframes; 28 | } 29 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/forms/_forms.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group forms 7 | //// 8 | 9 | /// Global spacing for form elements. 10 | /// @type Number 11 | $form-spacing: rem-calc(16) !default; 12 | 13 | @import 'text'; 14 | @import 'checkbox'; 15 | @import 'label'; 16 | @import 'help-text'; 17 | @import 'input-group'; 18 | @import 'fieldset'; 19 | @import 'select'; 20 | @import 'range'; 21 | @import 'progress'; 22 | @import 'meter'; 23 | @import 'error'; 24 | 25 | @mixin foundation-forms { 26 | @include foundation-form-text; 27 | @include foundation-form-checkbox; 28 | @include foundation-form-label; 29 | @include foundation-form-helptext; 30 | @include foundation-form-prepostfix; 31 | @include foundation-form-fieldset; 32 | @include foundation-form-select; 33 | @include foundation-form-error; 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/io/bit3/jsass/adapter/NativeTestAdapter.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.adapter; 2 | 3 | public class NativeTestAdapter { 4 | static { 5 | NativeTestLoader.loadTestLibrary(); 6 | } 7 | 8 | public native Object testSassPositiveNumberToJava(); 9 | 10 | public native Object testSassNegativeNumberToJava(); 11 | 12 | public native Object testSassZeroNumberToJava(); 13 | 14 | public native Object testSassPositiveNumberWithUnitToJava(); 15 | 16 | public native Object testSassNegativeNumberWithUnitToJava(); 17 | 18 | public native Object testSassZeroNumberWithUnitToJava(); 19 | 20 | public native Object testSassStringToJava(); 21 | 22 | public native Object testSassQuotedStringToJava(); 23 | 24 | public native Object testSassTrueToJava(); 25 | 26 | public native Object testSassFalseToJava(); 27 | 28 | public native Object testSassRgbColorToJava(); 29 | 30 | public native Object testSassRgbaColorToJava(); 31 | } 32 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/components/_accordion-menu.scss: -------------------------------------------------------------------------------- 1 | //// 2 | /// @group accordion-menu 3 | //// 4 | 5 | /// Sets if accordion menus have the default arrow styles. 6 | /// @type Boolean 7 | $accordionmenu-arrows: true !default; 8 | 9 | /// Sets accordion menu arrow color if arrow is used. 10 | /// @type Color 11 | $accordionmenu-arrow-color: $primary-color !default; 12 | 13 | @mixin foundation-accordion-menu { 14 | @if $accordionmenu-arrows { 15 | .is-accordion-submenu-parent > a { 16 | position: relative; 17 | 18 | &::after { 19 | @include css-triangle(6px, $accordionmenu-arrow-color, down); 20 | position: absolute; 21 | top: 50%; 22 | margin-top: -4px; 23 | right: 1rem; 24 | } 25 | } 26 | 27 | .is-accordion-submenu-parent[aria-expanded='true'] > a::after { 28 | transform-origin: 50% 50%; 29 | transform: scaleY(-1); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/converter/ContextArgumentConverter.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.converter; 2 | 3 | import io.bit3.jsass.context.Context; 4 | import io.bit3.jsass.context.ImportStack; 5 | import io.bit3.jsass.function.FunctionArgumentSignature; 6 | import io.bit3.jsass.function.FunctionArgumentSignatureFactory; 7 | 8 | import java.lang.reflect.Method; 9 | import java.lang.reflect.Parameter; 10 | import java.util.LinkedList; 11 | import java.util.List; 12 | 13 | public class ContextArgumentConverter implements ArgumentConverter { 14 | 15 | @Override 16 | public Object convert( 17 | List remainingArguments, ImportStack importStack, Context context) { 18 | return context; 19 | } 20 | 21 | @Override 22 | public List argumentSignatures( 23 | Object object, Method method, Parameter parameter, FunctionArgumentSignatureFactory factory 24 | ) { 25 | return new LinkedList<>(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/util/_selector.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group functions 7 | //// 8 | 9 | /// Generates a selector with every text input type. You can also filter the list to only output a subset of those selectors. 10 | /// 11 | /// @param {List|Keyword} $types [()] - A list of text input types to use. Leave blank to use all of them. 12 | @function text-inputs($types: ()) { 13 | $return: (); 14 | 15 | $all-types: 16 | text 17 | password 18 | date 19 | datetime 20 | datetime-local 21 | month 22 | week 23 | email 24 | number 25 | search 26 | tel 27 | time 28 | url 29 | color; 30 | 31 | @if not has-value($types) { 32 | $types: $all-types; 33 | } 34 | 35 | @each $type in $types { 36 | $return: append($return, unquote('[type=\'#{$type}\']'), comma); 37 | } 38 | 39 | @return $return; 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/JsassCustomFunctions.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function; 2 | 3 | import io.bit3.jsass.context.ImportStack; 4 | 5 | import java.net.URISyntaxException; 6 | 7 | /** 8 | * Provider of jsass specific callback functions. 9 | */ 10 | public class JsassCustomFunctions { 11 | /** 12 | * The import stack. 13 | */ 14 | private final ImportStack importStack; 15 | 16 | /** 17 | * Create a new function provider. 18 | */ 19 | public JsassCustomFunctions(ImportStack importStack) { 20 | this.importStack = importStack; 21 | } 22 | 23 | /** 24 | * Push an import to the import stack. 25 | */ 26 | public Object jsass_import_stack_push(int id) 27 | throws URISyntaxException { 28 | this.importStack.push(id); 29 | 30 | return null; 31 | } 32 | 33 | /** 34 | * Pop an import from the import stack. 35 | */ 36 | public Object jsass_import_stack_pop() { 37 | this.importStack.pop(); 38 | 39 | return null; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/forms/_checkbox.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group forms 7 | //// 8 | 9 | @mixin foundation-form-checkbox { 10 | [type='file'], 11 | [type='checkbox'], 12 | [type='radio'] { 13 | margin: 0 0 $form-spacing; 14 | } 15 | 16 | // Styles for input/label siblings 17 | [type='checkbox'] + label, 18 | [type='radio'] + label { 19 | display: inline-block; 20 | margin-#{$global-left}: $form-spacing * 0.5; 21 | margin-#{$global-right}: $form-spacing; 22 | margin-bottom: 0; 23 | vertical-align: baseline; 24 | 25 | &[for] { 26 | cursor: pointer; 27 | } 28 | } 29 | 30 | // Styles for inputs inside labels 31 | label > [type='checkbox'], 32 | label > [type='radio'] { 33 | margin-#{$global-right}: $form-spacing * 0.5; 34 | } 35 | 36 | // Normalize file input width 37 | [type='file'] { 38 | width: 100%; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/Output.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * The SASS compilation output. 7 | */ 8 | public class Output implements Serializable { 9 | private static final long serialVersionUID = 5649502387645755010L; 10 | 11 | /** 12 | * The css output. 13 | */ 14 | private final String css; 15 | 16 | /** 17 | * The source map output. 18 | */ 19 | private final String sourceMap; 20 | 21 | /** 22 | * Create a new output. 23 | */ 24 | public Output( 25 | String css, 26 | String sourceMap 27 | ) { 28 | this.css = css; 29 | this.sourceMap = sourceMap; 30 | } 31 | 32 | /** 33 | * Get the css output. 34 | * 35 | * @return The css output. 36 | */ 37 | public String getCss() { 38 | return css; 39 | } 40 | 41 | /** 42 | * Get the source map output. 43 | * 44 | * @return The source map output. 45 | */ 46 | public String getSourceMap() { 47 | return sourceMap; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/resources/scss/input.scss: -------------------------------------------------------------------------------- 1 | // imported through include-path 2 | @import "mixins"; 3 | 4 | // imported through custom importer 5 | @import "include"; 6 | 7 | // custom functions 8 | @import "functions"; 9 | 10 | .unit-test { 11 | display: block; 12 | 13 | .compile { 14 | font-size: 16px; 15 | } 16 | 17 | .world { 18 | content: hello(); 19 | } 20 | 21 | .globe { 22 | content: hello("globe"); 23 | } 24 | 25 | .increment { 26 | z-index: increment(10); 27 | } 28 | 29 | .increment-five { 30 | z-index: increment(10, 5); 31 | } 32 | 33 | .decrement { 34 | z-index: decrement(10); 35 | } 36 | 37 | .decrement-five { 38 | z-index: decrement(10, 5); 39 | } 40 | 41 | // issue #73 42 | .operatory { 43 | $input-padding-y: 0.5rem; 44 | $input-border-width: 1px; 45 | 46 | padding-top: calc(#{$input-padding-y} + #{$input-border-width}); 47 | } 48 | } 49 | 50 | @warn "I'm a warn message"; 51 | @error "I'm an error message"; 52 | @debug "I'm a debug message"; 53 | -------------------------------------------------------------------------------- /bin/make-libjsass-darwin.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | cd `dirname $0`; 6 | cd ..; 7 | 8 | JSASS_BASE_DIR=`pwd`; 9 | 10 | cd src/main; 11 | 12 | rm -r resources/darwin 13 | mkdir -p resources/darwin 14 | 15 | # *** Build libsass 16 | 17 | make -C libsass clean 18 | cd libsass 19 | git reset --hard # hard reset 20 | git clean -xdf # hard clean 21 | cd .. 22 | 23 | # We use: 24 | # - BUILD="static" to make sure that we build a static library 25 | BUILD="static" make -C libsass -j5 26 | 27 | # *** Build libjsass 28 | 29 | rm -r c/build 30 | mkdir -p c/build 31 | cd c/build 32 | cmake ../ || exit 1 33 | make -j5 || exit 1 34 | cp libjsass.dylib ../../resources/darwin/libjsass.dylib 35 | 36 | # *** Build libjsass_test 37 | 38 | cd $JSASS_BASE_DIR; 39 | cd src/test; 40 | 41 | rm -r resources/darwin 42 | mkdir -p resources/darwin 43 | 44 | rm -r c/build 45 | mkdir -p c/build 46 | cd c/build 47 | cmake ../ || exit 1 48 | make -j5 || exit 1 49 | cp libjsass_test.dylib ../../resources/darwin/libjsass_test.dylib 50 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/util/_selector.scss: -------------------------------------------------------------------------------- 1 | /// Builds a selector for a motion class, using the settings defined in the `$motion-ui-classes` and `$motion-ui-states` maps. 2 | /// @param {String|List} $states - One or more strings that correlate to a state. 3 | /// @param {Boolean} $active - Defines if the selector is for the setup or active class. 4 | /// @return {String} A selector that can be interpolated into your Sass code. 5 | /// @access private 6 | @function -mui-build-selector($states, $active: false) { 7 | $return: ''; 8 | $chain: map-get($motion-ui-classes, chain); 9 | $prefix: map-get($motion-ui-classes, prefix); 10 | $suffix: map-get($motion-ui-classes, active); 11 | 12 | @each $sel in $states { 13 | $return: $return + if($chain, '&.', '#{&}-') + $prefix + $sel; 14 | 15 | @if $active { 16 | $return: $return + if($chain, '.', '#{&}-') + $prefix + $sel + $suffix; 17 | } 18 | 19 | $return: $return + ', '; 20 | } 21 | 22 | @return str-slice($return, 1, -3); 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/io/bit3/jsass/adapter/NativeTestLoader.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.adapter; 2 | 3 | import java.io.File; 4 | 5 | /** 6 | * This loader handle the extraction and loading of the shared library files from the jar. 7 | */ 8 | final class NativeTestLoader { 9 | /** 10 | * Load the shared libraries. 11 | */ 12 | public static void loadTestLibrary() { 13 | try { 14 | File tmpDir = new File(System.getProperty("java.io.tmpdir")); 15 | File dir = File.createTempFile("libjsass-", ".d", tmpDir); 16 | dir.delete(); 17 | dir.mkdir(); 18 | dir.deleteOnExit(); 19 | 20 | if (System.getProperty("os.name").toLowerCase().startsWith("win")) { 21 | System.load(NativeLoader.saveLibrary(dir, "sass")); 22 | } 23 | 24 | System.load(NativeLoader.saveLibrary(dir, "jsass_test")); 25 | } catch (Exception exception) { 26 | System.err.println(exception.getMessage()); 27 | exception.printStackTrace(System.err); 28 | throw new RuntimeException(exception); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/converter/LastImportArgumentConverter.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.converter; 2 | 3 | import io.bit3.jsass.context.Context; 4 | import io.bit3.jsass.context.ImportStack; 5 | import io.bit3.jsass.function.FunctionArgumentSignature; 6 | import io.bit3.jsass.function.FunctionArgumentSignatureFactory; 7 | 8 | import java.lang.reflect.Method; 9 | import java.lang.reflect.Parameter; 10 | import java.util.LinkedList; 11 | import java.util.List; 12 | 13 | /** 14 | * Inject the current import as argument. 15 | */ 16 | public class LastImportArgumentConverter implements ArgumentConverter { 17 | @Override 18 | public Object convert( 19 | List remainingArguments, ImportStack importStack, Context context 20 | ) { 21 | return importStack.peek(); 22 | } 23 | 24 | @Override 25 | public List argumentSignatures( 26 | Object object, Method method, Parameter parameter, FunctionArgumentSignatureFactory factory 27 | ) { 28 | return new LinkedList<>(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/io/bit3/jsass/Sass2ScssTest.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass; 2 | 3 | import org.apache.commons.io.IOUtils; 4 | 5 | import java.io.File; 6 | import java.io.IOException; 7 | import java.net.URISyntaxException; 8 | import java.net.URL; 9 | 10 | import org.junit.jupiter.api.Test; 11 | import org.junit.jupiter.api.Assertions; 12 | import static org.junit.jupiter.api.Assertions.*; 13 | 14 | public class Sass2ScssTest extends AbstractCompileTest { 15 | public Sass2ScssTest() { 16 | super(); 17 | } 18 | 19 | @Test 20 | public void testConvert () throws Exception { 21 | URL sourceUrl = getClass().getResource("/sass/input.sass"); 22 | String source = IOUtils.toString(sourceUrl); 23 | 24 | int options = Sass2ScssOptions.PRETTIFY2 | Sass2ScssOptions.KEEP_COMMENT; 25 | String converted_output = Compiler.sass2scss(source, options); 26 | 27 | URL outputUrl = getClass().getResource("/scss/input.scss"); 28 | String real_output = IOUtils.toString(outputUrl); 29 | 30 | Assertions.assertEquals(real_output, converted_output); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * jsass is a feature complete java sass compiler, 3 | * using libsass. 4 | * 5 | *

You should start with the {@link io.bit3.jsass.Compiler} class, 6 | * here is a short quick start example.

7 | *
 8 |  * String input = "body { color: red; }";
 9 |  * URI inputFile = new File("stylesheet.scss").toURI();
10 |  * URI outputFile = new File("stylesheet.css").toURI();
11 |  *
12 |  * Compiler compiler = new Compiler();
13 |  * Options options = new Options();
14 |  *
15 |  * try {
16 |  *   Output output = compiler.compileString(input, inputFile, outputFile, options);
17 |  *
18 |  *   out.println("Compiled successfully");
19 |  *   out.println(output.getCss());
20 |  * } catch (CompilationException e) {
21 |  *   err.println("Compile failed");
22 |  *   err.println(e.getErrorText());
23 |  * }
24 |  * 
25 | *

You will find more examples 26 | * in the documentation.

27 | */ 28 | package io.bit3.jsass; 29 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/transitions/_fade.scss: -------------------------------------------------------------------------------- 1 | /// Creates a fade transition by adjusting the opacity of the element. 2 | /// @param {Keyword} $state [in] - State to transition to. 3 | /// @param {Number} $from [0] - Opacity to start at. Must be a number between 0 and 1. 4 | /// @param {Number} $to [1] - Opacity to end on. 5 | /// @param {Keyword} $duration [null] - Length (speed) of the transition. 6 | /// @param {Keyword|Function} $timing [null] - Easing of the transition. 7 | /// @param {Duration} $delay [null] - Delay in seconds or milliseconds before the transition starts. 8 | @mixin mui-fade( 9 | $state: in, 10 | $from: 0, 11 | $to: 1, 12 | $duration: null, 13 | $timing: null, 14 | $delay: null 15 | ) { 16 | $fade: fade($from, $to); 17 | 18 | @include transition-start($state) { 19 | @include transition-basics($duration, $timing, $delay); 20 | @include -mui-keyframe-get($fade, 0); 21 | 22 | transition-property: opacity; 23 | } 24 | 25 | @include transition-end($state) { 26 | @include -mui-keyframe-get($fade, 100); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2024 Tristan Lins 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/context/StringContext.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.context; 2 | 3 | import io.bit3.jsass.Options; 4 | 5 | import java.net.URI; 6 | 7 | /** 8 | * A context to compile a string in memory. 9 | */ 10 | public class StringContext extends AbstractContext { 11 | private static final long serialVersionUID = -3016862884676346652L; 12 | 13 | /** 14 | * The in-memory sass code. 15 | */ 16 | private String string; 17 | 18 | /** 19 | * Create a new string context. 20 | * 21 | * @param string The in-memory sass code. 22 | * @param inputPath The input path used for calculation path changes, or null. 23 | * @param outputPath The output path used for calculation path changes, or null. 24 | * @param options The compiler options. 25 | */ 26 | public StringContext(String string, URI inputPath, URI outputPath, Options options) { 27 | super(inputPath, outputPath, options); 28 | this.string = string; 29 | } 30 | 31 | /** 32 | * Return the in-memory sass code. 33 | * 34 | * @return The in-memory sass code. 35 | */ 36 | public String getString() { 37 | return string; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/FunctionWrapper.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function; 2 | 3 | import io.bit3.jsass.type.SassList; 4 | import io.bit3.jsass.type.SassValue; 5 | 6 | /** 7 | * Wraps a java function as libsass function and pass the arguments through. 8 | */ 9 | public class FunctionWrapper { 10 | 11 | /** 12 | * The original function declaration, that is created by the factory. 13 | */ 14 | private final FunctionDeclaration declaration; 15 | 16 | /** 17 | * Create a new wrapper for the given function. 18 | * 19 | * @param declaration The function declaration. 20 | */ 21 | public FunctionWrapper(FunctionDeclaration declaration) { 22 | this.declaration = declaration; 23 | } 24 | 25 | public FunctionDeclaration getDeclaration() { 26 | return declaration; 27 | } 28 | 29 | /** 30 | * Call the function. 31 | */ 32 | public SassValue apply(SassValue value) { 33 | SassList sassList; 34 | 35 | if (value instanceof SassList) { 36 | sassList = (SassList) value; 37 | } else { 38 | sassList = new SassList(); 39 | sassList.add(value); 40 | } 41 | 42 | return declaration.invoke(sassList); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/grid/_gutter.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group grid 7 | //// 8 | 9 | /// Collapse the gutters on a column by removing the padding. **Note:** only use this mixin within a breakpoint. To collapse a column's gutters on all screen sizes, use the `$gutter` parameter of the `grid-column()` mixin instead. 10 | @mixin grid-column-collapse { 11 | padding-left: 0; 12 | padding-right: 0; 13 | } 14 | 15 | /// Un-collapse the gutters on a column by re-adding the padding. 16 | /// 17 | /// @param {Number} $gutter [$grid-column-gutter] - Spacing between columns. 18 | @mixin grid-column-uncollapse($gutter: $grid-column-gutter) { 19 | $gutter: rem-calc($gutter) / 2; 20 | padding-left: $gutter; 21 | padding-right: $gutter; 22 | } 23 | 24 | /// Shorthand for `grid-column-collapse()`. 25 | /// @alias grid-column-collapse 26 | @mixin grid-col-collapse { 27 | @include grid-column-collapse; 28 | } 29 | 30 | /// Shorthand for `grid-column-uncollapse()`. 31 | /// @alias grid-column-uncollapse 32 | @mixin grid-col-uncollapse($gutter: $grid-column-gutter) { 33 | @include grid-column-uncollapse($gutter); 34 | } 35 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/effects/_slide.scss: -------------------------------------------------------------------------------- 1 | /// Creates a sliding animation. 2 | /// @param {Keyword} $state [in] - Whether to move to (`in`) or from (`out`) the element's default position. 3 | /// @param {Keyword} $direction [up] - Direction to move. Can be `up`, `down`, `left`, or `right`. 4 | /// @param {Number} $amount [100%] - Distance to move. Can be any CSS length unit. 5 | /// @return {Map} A keyframes map that can be used with the `generate-keyframes()` mixin. 6 | @function slide( 7 | $state: in, 8 | $direction: up, 9 | $amount: 100% 10 | ) { 11 | $from: $amount; 12 | $to: 0; 13 | $func: 'translateY'; 14 | 15 | @if $direction == left or $direction == right { 16 | $func: 'translateX'; 17 | } 18 | 19 | @if $state == out { 20 | $from: 0; 21 | $to: $amount; 22 | } 23 | 24 | @if $direction == down or $direction == right { 25 | @if $state == in { 26 | $from: -$from; 27 | } 28 | } @else { 29 | @if $state == out { 30 | $to: -$to; 31 | } 32 | } 33 | 34 | $keyframes: ( 35 | name: 'slide-#{$state}-#{$direction}-#{strip-unit($amount)}', 36 | 0: (transform: '#{$func}(#{$from})'), 37 | 100: (transform: '#{$func}(#{$to})'), 38 | ); 39 | 40 | @return $keyframes; 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/context/ImportStack.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.context; 2 | 3 | import io.bit3.jsass.importer.Import; 4 | 5 | import java.util.Deque; 6 | import java.util.HashMap; 7 | import java.util.LinkedList; 8 | import java.util.Map; 9 | 10 | /** 11 | * Stack for tracking currently evaluated file. 12 | */ 13 | public class ImportStack { 14 | 15 | /** 16 | * A registry where each import will be registered by an incrementing ID. 17 | */ 18 | private Map registry = new HashMap<>(); 19 | 20 | /** 21 | * The current import stack. 22 | */ 23 | private Deque stack = new LinkedList<>(); 24 | 25 | /** 26 | * Register a new import, return the registration ID. 27 | */ 28 | public int register(Import importSource) { 29 | int id = registry.size() + 1; 30 | registry.put(id, importSource); 31 | return id; 32 | } 33 | 34 | /** 35 | * Push an import to the stack by its ID. 36 | */ 37 | public void push(int id) { 38 | stack.push(registry.get(id)); 39 | } 40 | 41 | /** 42 | * Pop an import from the stack. 43 | */ 44 | public void pop() { 45 | stack.pop(); 46 | } 47 | 48 | /** 49 | * Return the current import. 50 | */ 51 | public Import peek() { 52 | return stack.peek(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/forms/_label.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group forms 7 | //// 8 | 9 | /// Color for form labels. 10 | /// @type Color 11 | $form-label-color: $black !default; 12 | 13 | /// Font size for form labels. 14 | /// @type Number 15 | $form-label-font-size: rem-calc(14) !default; 16 | 17 | /// Font weight for form labels. 18 | /// @type Keyword 19 | $form-label-font-weight: $global-weight-normal !default; 20 | 21 | /// Line height for form labels. The higher the number, the more space between the label and its input field. 22 | /// @type Number 23 | $form-label-line-height: 1.8 !default; 24 | 25 | @mixin form-label { 26 | display: block; 27 | margin: 0; 28 | font-size: $form-label-font-size; 29 | font-weight: $form-label-font-weight; 30 | line-height: $form-label-line-height; 31 | color: $form-label-color; 32 | } 33 | 34 | @mixin form-label-middle { 35 | $input-border-width: get-border-value($input-border, width); 36 | margin: 0 0 $form-spacing; 37 | padding: ($form-spacing / 2 + rem-calc($input-border-width)) 0; 38 | } 39 | 40 | @mixin foundation-form-label { 41 | label { 42 | @include form-label; 43 | 44 | &.middle { 45 | @include form-label-middle; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/forms/_fieldset.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group forms 7 | //// 8 | 9 | /// Default border around custom fieldsets. 10 | /// @type Border 11 | $fieldset-border: 1px solid $medium-gray !default; 12 | 13 | /// Default padding inside custom fieldsets. 14 | /// @type Number 15 | $fieldset-padding: rem-calc(20) !default; 16 | 17 | /// Default margin around custom fieldsets. 18 | /// @type Number 19 | $fieldset-margin: rem-calc(18 0) !default; 20 | 21 | /// Default padding between the legend text and fieldset border. 22 | /// @type Number 23 | $legend-padding: rem-calc(0 3) !default; 24 | 25 | @mixin fieldset { 26 | border: $fieldset-border; 27 | padding: $fieldset-padding; 28 | margin: $fieldset-margin; 29 | 30 | legend { 31 | // Covers up the fieldset's border to create artificial padding 32 | background: $body-background; 33 | padding: $legend-padding; 34 | margin: 0; 35 | margin-#{$global-left}: rem-calc(-3); 36 | } 37 | } 38 | 39 | @mixin foundation-form-fieldset { 40 | fieldset { 41 | border: 0; 42 | padding: 0; 43 | margin: 0; 44 | } 45 | 46 | legend { 47 | margin-bottom: $form-spacing * 0.5; 48 | max-width: 100%; 49 | } 50 | 51 | .fieldset { 52 | @include fieldset; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/context/AbstractContext.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.context; 2 | 3 | import io.bit3.jsass.Options; 4 | 5 | import java.net.URI; 6 | 7 | /** 8 | * Abstract context that contain all shared informations for each context. 9 | */ 10 | public abstract class AbstractContext implements Context { 11 | private static final long serialVersionUID = 913074077778518500L; 12 | 13 | /** 14 | * The input file path. 15 | */ 16 | private final URI inputPath; 17 | 18 | /** 19 | * The output file path. 20 | */ 21 | private final URI outputPath; 22 | 23 | /** 24 | * The compiler options. 25 | */ 26 | private final Options options; 27 | 28 | /** 29 | * Initialize the context with input path, output path and options. 30 | * 31 | * @param inputPath The input file path. 32 | * @param outputPath The output file path. 33 | * @param options The compiler options. 34 | */ 35 | public AbstractContext(URI inputPath, URI outputPath, Options options) { 36 | this.inputPath = inputPath; 37 | this.outputPath = outputPath; 38 | this.options = options; 39 | } 40 | 41 | @Override 42 | public URI getInputPath() { 43 | return inputPath; 44 | } 45 | 46 | @Override 47 | public URI getOutputPath() { 48 | return outputPath; 49 | } 50 | 51 | @Override 52 | public Options getOptions() { 53 | return options; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/type/SassMap.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.type; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | import java.util.stream.Collectors; 6 | 7 | /** 8 | * A sass value list. 9 | */ 10 | public class SassMap extends LinkedHashMap implements SassValue { 11 | private static final long serialVersionUID = -65270174805160025L; 12 | public static final int TYPE = 7; 13 | 14 | public SassMap() { 15 | // an empty map 16 | } 17 | 18 | public SassMap(Map map) { 19 | super(map); 20 | } 21 | 22 | public SassMap(int initialCapacity) { 23 | super(initialCapacity); 24 | } 25 | 26 | public SassMap(int initialCapacity, float loadFactor) { 27 | super(initialCapacity, loadFactor); 28 | } 29 | 30 | public SassMap(int initialCapacity, float loadFactor, boolean accessOrder) { 31 | super(initialCapacity, loadFactor, accessOrder); 32 | } 33 | 34 | /** 35 | * Return a libsass compatible (key: value) string representation. 36 | * 37 | * @return A libsass compatible (key: value) string representation. 38 | */ 39 | @Override 40 | public String toString() { 41 | String map = entrySet() 42 | .stream() 43 | .map(e -> e.getKey() + ": " + e.getValue()) 44 | .collect(Collectors.joining(", ")); 45 | 46 | return "(" + map + ")"; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/components/_badge.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group badge 7 | //// 8 | 9 | /// Default background color for badges. 10 | /// @type Color 11 | $badge-background: $primary-color !default; 12 | 13 | /// Default text color for badges. 14 | /// @type Color 15 | $badge-color: foreground($badge-background) !default; 16 | 17 | /// Default padding inside badges. 18 | /// @type Number 19 | $badge-padding: 0.3em !default; 20 | 21 | /// Minimum width of a badge. 22 | /// @type Number 23 | $badge-minwidth: 2.1em !default; 24 | 25 | /// Default font size for badges. 26 | /// @type Number 27 | $badge-font-size: 0.6rem !default; 28 | 29 | /// Generates the base styles for a badge. 30 | @mixin badge { 31 | display: inline-block; 32 | padding: $badge-padding; 33 | min-width: $badge-minwidth; 34 | font-size: $badge-font-size; 35 | text-align: center; 36 | border-radius: 50%; 37 | } 38 | 39 | @mixin foundation-badge { 40 | .badge { 41 | @include badge; 42 | 43 | background: $badge-background; 44 | color: $badge-color; 45 | 46 | @each $name, $color in $foundation-palette { 47 | @if $name != primary { 48 | &.#{$name} { 49 | background: $color; 50 | color: foreground($color); 51 | } 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/io/bit3/jsass/AbstractCompileTest.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass; 2 | 3 | import org.apache.commons.io.IOUtils; 4 | import org.junit.jupiter.api.Assertions; 5 | 6 | import java.io.IOException; 7 | import java.net.URL; 8 | import java.nio.charset.StandardCharsets; 9 | import java.util.Collections; 10 | 11 | abstract class AbstractCompileTest { 12 | String syntax; 13 | OutputStyle outputStyle; 14 | TestFunctions testFunctions; 15 | 16 | AbstractCompileTest() { 17 | this.testFunctions = new TestFunctions(); 18 | } 19 | 20 | void assertEquals(String actual, URL expectedSource) throws IOException { 21 | String expected = IOUtils.toString(expectedSource, StandardCharsets.UTF_8); 22 | 23 | Assertions.assertEquals( 24 | expected, 25 | Utils.dos2unix(actual), 26 | () -> String.format("Compile input.%s into %s output format failed", syntax, outputStyle) 27 | ); 28 | } 29 | 30 | void assertSpecialFunctions() { 31 | Assertions.assertEquals( 32 | Collections.singletonList("I'm a warn message"), 33 | testFunctions.warnMessages 34 | ); 35 | Assertions.assertEquals( 36 | Collections.singletonList("I'm an error message"), 37 | testFunctions.errorMessages 38 | ); 39 | Assertions.assertEquals( 40 | Collections.singletonList("I'm a debug message"), 41 | testFunctions.debugMessages 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/grid/_layout.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group grid 7 | //// 8 | 9 | /// Sizes child elements so that `$n` number of items appear on each row. 10 | /// 11 | /// @param {Number} $n - Number of elements to display per row. 12 | /// @param {String} $selector ['.column'] - Selector(s) to use for child elements. 13 | @mixin grid-layout( 14 | $n, 15 | $selector: '.column' 16 | ) { 17 | & > #{$selector} { 18 | width: percentage(1/$n); 19 | float: $global-left; 20 | 21 | &:nth-of-type(1n) { 22 | clear: none; 23 | } 24 | 25 | &:nth-of-type(#{$n}n+1) { 26 | clear: both; 27 | } 28 | 29 | &:last-child { 30 | float: left; 31 | } 32 | } 33 | } 34 | 35 | /// Adds extra CSS to block grid children so the last items in the row center automatically. Apply this to the columns, not the row. 36 | /// 37 | /// @param {Number} $n - Number of items that appear in each row. 38 | @mixin grid-layout-center-last($n) { 39 | @for $i from 1 to $n { 40 | @if $i == 1 { 41 | &:nth-child(#{$n}n+1):last-child { 42 | margin-left: (100 - 100/$n * $i) / 2 * 1%; 43 | } 44 | } 45 | @else { 46 | &:nth-child(#{$n}n+1):nth-last-child(#{$i}) { 47 | margin-left: (100 - 100/$n * $i) / 2 * 1%; 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/converter/StringArgumentConverter.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.converter; 2 | 3 | import io.bit3.jsass.context.Context; 4 | import io.bit3.jsass.context.ImportStack; 5 | import io.bit3.jsass.function.FunctionArgumentSignature; 6 | import io.bit3.jsass.function.FunctionArgumentSignatureFactory; 7 | import io.bit3.jsass.type.SassNull; 8 | import io.bit3.jsass.type.SassString; 9 | 10 | import java.lang.reflect.Method; 11 | import java.lang.reflect.Parameter; 12 | import java.util.List; 13 | 14 | public class StringArgumentConverter implements ArgumentConverter { 15 | 16 | @Override 17 | public Object convert( 18 | List remainingArguments, ImportStack importStack, Context context) { 19 | if (remainingArguments.isEmpty()) { 20 | return null; 21 | } 22 | 23 | Object value = remainingArguments.remove(0); 24 | 25 | // ignore null value 26 | if (null == value || value instanceof SassNull) { 27 | return null; 28 | } 29 | 30 | if (value instanceof SassString) { 31 | return ((SassString) value).getValue(); 32 | } 33 | 34 | return value.toString(); 35 | } 36 | 37 | @Override 38 | public List argumentSignatures( 39 | Object object, Method method, Parameter parameter, FunctionArgumentSignatureFactory factory 40 | ) { 41 | return factory.createDefaultArgumentSignature(parameter); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/components/_label.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group label 7 | //// 8 | 9 | /// Default background color for labels. 10 | /// @type Color 11 | $label-background: $primary-color !default; 12 | 13 | /// Default text color for labels. 14 | /// @type Color 15 | $label-color: foreground($label-background) !default; 16 | 17 | /// Default font size for labels. 18 | /// @type Number 19 | $label-font-size: 0.8rem !default; 20 | 21 | /// Default padding inside labels. 22 | /// @type Number 23 | $label-padding: 0.33333rem 0.5rem !default; 24 | 25 | /// Default radius of labels. 26 | /// @type Number 27 | $label-radius: $global-radius !default; 28 | 29 | /// Generates base styles for a label. 30 | @mixin label { 31 | display: inline-block; 32 | padding: $label-padding; 33 | font-size: $label-font-size; 34 | line-height: 1; 35 | white-space: nowrap; 36 | cursor: default; 37 | border-radius: $label-radius; 38 | } 39 | 40 | @mixin foundation-label { 41 | .label { 42 | @include label; 43 | 44 | background: $label-background; 45 | color: $label-color; 46 | 47 | @each $name, $color in $foundation-palette { 48 | @if $name != primary { 49 | &.#{$name} { 50 | background: $color; 51 | color: foreground($color); 52 | } 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /bin/make-libjsass-linux-x64-local.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo 4 | echo -e "\e[91m+-------------------------------------------------------------------------+\e[0m" 5 | echo -e "\e[91m| |\e[0m" 6 | echo -e "\e[91m| !!! Attention !!! This file is intended for local development only! |\e[0m" 7 | echo -e "\e[91m| |\e[0m" 8 | echo -e "\e[91m+-------------------------------------------------------------------------+\e[0m" 9 | echo 10 | 11 | set -xeuo pipefail 12 | 13 | BASE_DIR=$(dirname $(dirname $(readlink -e "$0"))) 14 | 15 | cd "$BASE_DIR/src/main" 16 | 17 | rm -fr resources/linux-x64 18 | mkdir -p resources/linux-x64 19 | 20 | # *** Build libsass 21 | 22 | make -C libsass clean 23 | cd libsass 24 | git reset --hard # hard reset 25 | git clean -xdf # hard clean 26 | cd .. 27 | 28 | # We use: 29 | # - BUILD="static" to make sure that we build a static library 30 | BUILD="static" make -C libsass -j4 31 | 32 | # *** Build libjsass 33 | 34 | rm -fr c/build 35 | mkdir -p c/build 36 | cd c/build 37 | cmake ../ 38 | make 39 | cp libjsass.so ../../resources/linux-x64/libjsass.so 40 | 41 | # *** Build libjsass_test 42 | 43 | cd "$BASE_DIR/src/test" 44 | 45 | rm -fr resources/linux-x64 46 | mkdir -p resources/linux-x64 47 | 48 | rm -fr c/build 49 | mkdir -p c/build 50 | cd c/build 51 | cmake ../ 52 | make 53 | cp libjsass_test.so ../../resources/linux-x64/libjsass_test.so 54 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/importer/JsassCustomHeaderImporter.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.importer; 2 | 3 | import io.bit3.jsass.context.ImportStack; 4 | 5 | import java.net.URI; 6 | import java.net.URISyntaxException; 7 | import java.util.Collection; 8 | import java.util.LinkedList; 9 | import java.util.List; 10 | 11 | public class JsassCustomHeaderImporter implements Importer { 12 | 13 | private final ImportStack importStack; 14 | 15 | public JsassCustomHeaderImporter(ImportStack importStack) { 16 | this.importStack = importStack; 17 | } 18 | 19 | @Override 20 | public Collection apply(String url, Import previous) { 21 | List list = new LinkedList<>(); 22 | 23 | list.add(createCustomHeaderImport(previous)); 24 | 25 | return list; 26 | } 27 | 28 | private Import createCustomHeaderImport(Import previous) { 29 | int id = importStack.register(previous); 30 | 31 | StringBuilder source = new StringBuilder(); 32 | 33 | // $jsass-void: jsass_import_stack_push(); 34 | source.append( 35 | String.format( 36 | "$jsass-void: jsass_import_stack_push(%d);%n", 37 | id 38 | ) 39 | ); 40 | 41 | try { 42 | return new Import( 43 | new URI(previous.getAbsoluteUri() + "/JSASS_CUSTOM.scss"), 44 | new URI(previous.getAbsoluteUri() + "/JSASS_CUSTOM.scss"), 45 | source.toString() 46 | ); 47 | } catch (URISyntaxException e) { 48 | throw new ImportException(e); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/components/_thumbnail.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group thumbnail 7 | //// 8 | 9 | /// Border around thumbnail images. 10 | /// @type Border 11 | $thumbnail-border: solid 4px $white !default; 12 | 13 | /// Bottom margin for thumbnail images. 14 | /// @type Length 15 | $thumbnail-margin-bottom: $global-margin !default; 16 | 17 | /// Box shadow under thumbnail images. 18 | /// @type Shadow 19 | $thumbnail-shadow: 0 0 0 1px rgba($black, 0.2) !default; 20 | 21 | /// Box shadow under thumbnail images. 22 | /// @type Shadow 23 | $thumbnail-shadow-hover: 0 0 6px 1px rgba($primary-color, 0.5) !default; 24 | 25 | /// Transition proprties for thumbnail images. 26 | /// @type Transition 27 | $thumbnail-transition: box-shadow 200ms ease-out !default; 28 | 29 | /// Default radius for thumbnail images. 30 | /// @type Number 31 | $thumbnail-radius: $global-radius !default; 32 | 33 | /// Adds thumbnail styles to an element. 34 | @mixin thumbnail { 35 | border: $thumbnail-border; 36 | box-shadow: $thumbnail-shadow; 37 | display: inline-block; 38 | line-height: 0; 39 | max-width: 100%; 40 | transition: $thumbnail-transition; 41 | border-radius: $thumbnail-radius; 42 | margin-bottom: $thumbnail-margin-bottom; 43 | 44 | &:hover, 45 | &:focus { 46 | box-shadow: $thumbnail-shadow-hover; 47 | } 48 | } 49 | 50 | @mixin foundation-thumbnail { 51 | .thumbnail { 52 | @include thumbnail; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/transitions/_zoom.scss: -------------------------------------------------------------------------------- 1 | /// Creates a scaling transition. A scale of `1` means the element is the same size. Larger numbers make the element bigger, while numbers less than 1 make the element smaller. 2 | /// @param {Keyword} $state [in] - State to transition to. 3 | /// @param {Number} $from [1.5] - Size to start at. 4 | /// @param {Number} $from [1] - Size to end at. 5 | /// @param {Boolean} $fade [true] - Set to `true` to fade the element in or out simultaneously. 6 | /// @param {Duration} $duration [null] - Length (speed) of the transition. 7 | /// @param {Keyword|Function} $timing [null] - Easing of the transition. 8 | /// @param {Duration} $delay [null] - Delay in seconds or milliseconds before the transition starts. 9 | @mixin mui-zoom( 10 | $state: in, 11 | $from: 1.5, 12 | $to: 1, 13 | $fade: map-get($motion-ui-settings, scale-and-fade), 14 | $duration: null, 15 | $timing: null, 16 | $delay: null 17 | ) { 18 | $scale: zoom($from, $to); 19 | 20 | @include transition-start($state) { 21 | @include transition-basics($duration, $timing, $delay); 22 | @include -mui-keyframe-get($scale, 0); 23 | 24 | @if $fade { 25 | transition-property: transform, opacity; 26 | opacity: if($state == in, 0, 1); 27 | } @else { 28 | transition-property: transform, opacity; 29 | } 30 | } 31 | 32 | @include transition-end($state) { 33 | @include -mui-keyframe-get($scale, 100); 34 | 35 | @if $fade { 36 | opacity: if($state == in, 1, 0); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/c/io_bit3_jsass_adapter_NativeAdapter.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class io_bit3_jsass_adapter_NativeAdapter */ 4 | 5 | #ifndef _Included_io_bit3_jsass_adapter_NativeAdapter 6 | #define _Included_io_bit3_jsass_adapter_NativeAdapter 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | /* 11 | * Class: io_bit3_jsass_adapter_NativeAdapter 12 | * Method: compileFile 13 | * Signature: (Lio/bit3/jsass/adapter/NativeFileContext;)Lio/bit3/jsass/Output; 14 | */ 15 | JNIEXPORT jobject JNICALL Java_io_bit3_jsass_adapter_NativeAdapter_compileFile 16 | (JNIEnv *, jclass, jobject); 17 | 18 | /* 19 | * Class: io_bit3_jsass_adapter_NativeAdapter 20 | * Method: compileString 21 | * Signature: (Lio/bit3/jsass/adapter/NativeStringContext;)Lio/bit3/jsass/Output; 22 | */ 23 | JNIEXPORT jobject JNICALL Java_io_bit3_jsass_adapter_NativeAdapter_compileString 24 | (JNIEnv *, jclass, jobject); 25 | 26 | /* 27 | * Class: io_bit3_jsass_adapter_NativeAdapter 28 | * Method: sass2scss 29 | * Signature: (Ljava/lang/String;I)Ljava/lang/String; 30 | */ 31 | JNIEXPORT jstring JNICALL Java_io_bit3_jsass_adapter_NativeAdapter_sass2scss 32 | (JNIEnv *, jclass, jstring, jint); 33 | 34 | /* 35 | * Class: io_bit3_jsass_adapter_NativeAdapter 36 | * Method: libsassVersion 37 | * Signature: ()Ljava/lang/String; 38 | */ 39 | JNIEXPORT jstring JNICALL Java_io_bit3_jsass_adapter_NativeAdapter_libsassVersion 40 | (JNIEnv *, jclass); 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | #endif 46 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/CompilationException.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass; 2 | 3 | public class CompilationException extends Exception { 4 | private static final long serialVersionUID = 630234764149041048L; 5 | 6 | /** 7 | * The error status, not zero means an error occurred. 8 | */ 9 | private final int errorStatus; 10 | 11 | private final String errorJson; 12 | 13 | private final String errorText; 14 | 15 | private final String errorMessage; 16 | 17 | private final String errorFile; 18 | 19 | private final String errorSrc; 20 | 21 | /** 22 | * Constructs a new exception. 23 | */ 24 | public CompilationException( 25 | int errorStatus, 26 | String errorJson, 27 | String errorText, 28 | String errorMessage, 29 | String errorFile, 30 | String errorSrc 31 | ) { 32 | super(errorMessage); 33 | this.errorStatus = errorStatus; 34 | this.errorJson = errorJson; 35 | this.errorText = errorText; 36 | this.errorMessage = errorMessage; 37 | this.errorFile = errorFile; 38 | this.errorSrc = errorSrc; 39 | } 40 | 41 | public int getErrorStatus() { 42 | return errorStatus; 43 | } 44 | 45 | public String getErrorJson() { 46 | return errorJson; 47 | } 48 | 49 | public String getErrorText() { 50 | return errorText; 51 | } 52 | 53 | public String getErrorMessage() { 54 | return errorMessage; 55 | } 56 | 57 | public String getErrorFile() { 58 | return errorFile; 59 | } 60 | 61 | public String getErrorSrc() { 62 | return errorSrc; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/converter/ByteArgumentConverter.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.converter; 2 | 3 | import io.bit3.jsass.context.Context; 4 | import io.bit3.jsass.context.ImportStack; 5 | import io.bit3.jsass.function.FunctionArgumentSignature; 6 | import io.bit3.jsass.function.FunctionArgumentSignatureFactory; 7 | import io.bit3.jsass.type.SassNull; 8 | import io.bit3.jsass.type.TypeUtils; 9 | 10 | import java.lang.reflect.Method; 11 | import java.lang.reflect.Parameter; 12 | import java.util.List; 13 | 14 | public class ByteArgumentConverter implements ArgumentConverter { 15 | 16 | @Override 17 | public Object convert( 18 | List remainingArguments, ImportStack importStack, Context context) { 19 | if (remainingArguments.isEmpty()) { 20 | return null; 21 | } 22 | 23 | Object value = remainingArguments.remove(0); 24 | 25 | // ignore null value 26 | if (null == value || value instanceof SassNull) { 27 | return null; 28 | } 29 | 30 | // value is already in a compatible type 31 | if (TypeUtils.isaByte(value.getClass())) { 32 | return value; 33 | } 34 | 35 | if (value instanceof Number) { 36 | value = ((Number) value).byteValue(); 37 | } else { 38 | value = Byte.parseByte(value.toString()); 39 | } 40 | 41 | return value; 42 | } 43 | 44 | @Override 45 | public List argumentSignatures( 46 | Object object, Method method, Parameter parameter, FunctionArgumentSignatureFactory factory 47 | ) { 48 | return factory.createDefaultArgumentSignature(parameter); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/converter/LongArgumentConverter.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.converter; 2 | 3 | import io.bit3.jsass.context.Context; 4 | import io.bit3.jsass.context.ImportStack; 5 | import io.bit3.jsass.function.FunctionArgumentSignature; 6 | import io.bit3.jsass.function.FunctionArgumentSignatureFactory; 7 | import io.bit3.jsass.type.SassNull; 8 | import io.bit3.jsass.type.TypeUtils; 9 | 10 | import java.lang.reflect.Method; 11 | import java.lang.reflect.Parameter; 12 | import java.util.List; 13 | 14 | public class LongArgumentConverter implements ArgumentConverter { 15 | 16 | @Override 17 | public Object convert( 18 | List remainingArguments, ImportStack importStack, Context context) { 19 | if (remainingArguments.isEmpty()) { 20 | return null; 21 | } 22 | 23 | Object value = remainingArguments.remove(0); 24 | 25 | // ignore null value 26 | if (null == value || value instanceof SassNull) { 27 | return null; 28 | } 29 | 30 | // value is already in a compatible type 31 | if (TypeUtils.isaLong(value.getClass())) { 32 | return value; 33 | } 34 | 35 | if (value instanceof Number) { 36 | value = ((Number) value).longValue(); 37 | } else { 38 | value = Long.parseLong(value.toString()); 39 | } 40 | 41 | return value; 42 | } 43 | 44 | @Override 45 | public List argumentSignatures( 46 | Object object, Method method, Parameter parameter, FunctionArgumentSignatureFactory factory 47 | ) { 48 | return factory.createDefaultArgumentSignature(parameter); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/converter/FloatArgumentConverter.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.converter; 2 | 3 | import io.bit3.jsass.context.Context; 4 | import io.bit3.jsass.context.ImportStack; 5 | import io.bit3.jsass.function.FunctionArgumentSignature; 6 | import io.bit3.jsass.function.FunctionArgumentSignatureFactory; 7 | import io.bit3.jsass.type.SassNull; 8 | import io.bit3.jsass.type.TypeUtils; 9 | 10 | import java.lang.reflect.Method; 11 | import java.lang.reflect.Parameter; 12 | import java.util.List; 13 | 14 | public class FloatArgumentConverter implements ArgumentConverter { 15 | 16 | @Override 17 | public Object convert( 18 | List remainingArguments, ImportStack importStack, Context context) { 19 | if (remainingArguments.isEmpty()) { 20 | return null; 21 | } 22 | 23 | Object value = remainingArguments.remove(0); 24 | 25 | // ignore null value 26 | if (null == value || value instanceof SassNull) { 27 | return null; 28 | } 29 | 30 | // value is already in a compatible type 31 | if (TypeUtils.isaFloat(value.getClass())) { 32 | return value; 33 | } 34 | 35 | if (value instanceof Number) { 36 | value = ((Number) value).floatValue(); 37 | } else { 38 | value = Float.parseFloat(value.toString()); 39 | } 40 | 41 | return value; 42 | } 43 | 44 | @Override 45 | public List argumentSignatures( 46 | Object object, Method method, Parameter parameter, FunctionArgumentSignatureFactory factory 47 | ) { 48 | return factory.createDefaultArgumentSignature(parameter); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/converter/ShortArgumentConverter.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.converter; 2 | 3 | import io.bit3.jsass.context.Context; 4 | import io.bit3.jsass.context.ImportStack; 5 | import io.bit3.jsass.function.FunctionArgumentSignature; 6 | import io.bit3.jsass.function.FunctionArgumentSignatureFactory; 7 | import io.bit3.jsass.type.SassNull; 8 | import io.bit3.jsass.type.TypeUtils; 9 | 10 | import java.lang.reflect.Method; 11 | import java.lang.reflect.Parameter; 12 | import java.util.List; 13 | 14 | public class ShortArgumentConverter implements ArgumentConverter { 15 | 16 | @Override 17 | public Object convert( 18 | List remainingArguments, ImportStack importStack, Context context) { 19 | if (remainingArguments.isEmpty()) { 20 | return null; 21 | } 22 | 23 | Object value = remainingArguments.remove(0); 24 | 25 | // ignore null value 26 | if (null == value || value instanceof SassNull) { 27 | return null; 28 | } 29 | 30 | // value is already in a compatible type 31 | if (TypeUtils.isaShort(value.getClass())) { 32 | return value; 33 | } 34 | 35 | if (value instanceof Number) { 36 | value = ((Number) value).shortValue(); 37 | } else { 38 | value = Short.parseShort(value.toString()); 39 | } 40 | 41 | return value; 42 | } 43 | 44 | @Override 45 | public List argumentSignatures( 46 | Object object, Method method, Parameter parameter, FunctionArgumentSignatureFactory factory 47 | ) { 48 | return factory.createDefaultArgumentSignature(parameter); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/converter/IntegerArgumentConverter.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.converter; 2 | 3 | import io.bit3.jsass.context.Context; 4 | import io.bit3.jsass.context.ImportStack; 5 | import io.bit3.jsass.function.FunctionArgumentSignature; 6 | import io.bit3.jsass.function.FunctionArgumentSignatureFactory; 7 | import io.bit3.jsass.type.SassNull; 8 | import io.bit3.jsass.type.TypeUtils; 9 | 10 | import java.lang.reflect.Method; 11 | import java.lang.reflect.Parameter; 12 | import java.util.List; 13 | 14 | public class IntegerArgumentConverter implements ArgumentConverter { 15 | 16 | @Override 17 | public Object convert( 18 | List remainingArguments, ImportStack importStack, Context context) { 19 | if (remainingArguments.isEmpty()) { 20 | return null; 21 | } 22 | 23 | Object value = remainingArguments.remove(0); 24 | 25 | // ignore null value 26 | if (null == value || value instanceof SassNull) { 27 | return null; 28 | } 29 | 30 | // value is already in a compatible type 31 | if (TypeUtils.isaInteger(value.getClass())) { 32 | return value; 33 | } 34 | 35 | if (value instanceof Number) { 36 | value = ((Number) value).intValue(); 37 | } else { 38 | value = Integer.parseInt(value.toString()); 39 | } 40 | 41 | return value; 42 | } 43 | 44 | @Override 45 | public List argumentSignatures( 46 | Object object, Method method, Parameter parameter, FunctionArgumentSignatureFactory factory 47 | ) { 48 | return factory.createDefaultArgumentSignature(parameter); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/components/_dropdown.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group dropdown 7 | //// 8 | 9 | /// Padding for dropdown panes. 10 | /// @type List 11 | $dropdown-padding: 1rem !default; 12 | 13 | /// Border for dropdown panes. 14 | /// @type List 15 | $dropdown-border: 1px solid $medium-gray !default; 16 | 17 | /// Font size for dropdown panes. 18 | /// @type List 19 | $dropdown-font-size: 1rem !default; 20 | 21 | /// Width for dropdown panes. 22 | /// @type Number 23 | $dropdown-width: 300px !default; 24 | 25 | /// Border radius dropdown panes. 26 | /// @type Number 27 | $dropdown-radius: $global-radius !default; 28 | 29 | /// Sizes for dropdown panes. Each size is a CSS class you can apply. 30 | /// @type Map 31 | $dropdown-sizes: ( 32 | tiny: 100px, 33 | small: 200px, 34 | large: 400px, 35 | ) !default; 36 | 37 | /// Applies styles for a basic dropdown. 38 | @mixin dropdown-container { 39 | background-color: $body-background; 40 | border: $dropdown-border; 41 | border-radius: $dropdown-radius; 42 | display: block; 43 | font-size: $dropdown-font-size; 44 | padding: $dropdown-padding; 45 | position: absolute; 46 | visibility: hidden; 47 | width: $dropdown-width; 48 | z-index: 10; 49 | 50 | &.is-open { 51 | visibility: visible; 52 | } 53 | } 54 | 55 | @mixin foundation-dropdown { 56 | .dropdown-pane { 57 | @include dropdown-container; 58 | } 59 | 60 | @each $name, $size in $dropdown-sizes { 61 | .dropdown-pane.#{$name} { 62 | width: $size; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/transitions/_spin.scss: -------------------------------------------------------------------------------- 1 | /// Creates a spinning transition by rotating the element. The `turn` unit is used to specify how far to rotate. `1turn` is equal to a 360-degree spin. 2 | /// @param {Keyword} $state [in] - State to transition to. 3 | /// @param {Boolean} $direction [cw] - Direction to spin. Should be `cw` (clockwise) or `ccw` (counterclockwise). 4 | /// @param {Number} $amount [0.75turn] - Amount to element the element. 5 | /// @param {Boolean} $fade [false] - Set to `true` to fade the element in or out simultaneously. 6 | /// @param {Duration} $duration [null] - Length (speed) of the transition. 7 | /// @param {Keyword|Function} $timing [null] - Easing of the transition. 8 | /// @param {Duration} $delay [null] - Delay in seconds or milliseconds before the transition starts. 9 | @mixin mui-spin( 10 | $state: in, 11 | $direction: cw, 12 | $amount: 0.75turn, 13 | $fade: map-get($motion-ui-settings, spin-and-fade), 14 | $duration: null, 15 | $timing: null, 16 | $delay: null 17 | ) { 18 | $spin: spin($state, $direction, $amount); 19 | 20 | @include transition-start($state) { 21 | @include transition-basics($duration, $timing, $delay); 22 | @include -mui-keyframe-get($spin, 0); 23 | 24 | @if $fade { 25 | transition-property: transform, opacity; 26 | opacity: if($state == in, 0, 1); 27 | } @else { 28 | transition-property: transform, opacity; 29 | } 30 | } 31 | 32 | @include transition-end($state) { 33 | @include -mui-keyframe-get($spin, 100); 34 | 35 | @if $fade { 36 | opacity: if($state == in, 1, 0); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/converter/CharacterArgumentConverter.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.converter; 2 | 3 | import io.bit3.jsass.context.Context; 4 | import io.bit3.jsass.context.ImportStack; 5 | import io.bit3.jsass.function.FunctionArgumentSignature; 6 | import io.bit3.jsass.function.FunctionArgumentSignatureFactory; 7 | import io.bit3.jsass.type.SassNull; 8 | import io.bit3.jsass.type.SassString; 9 | import io.bit3.jsass.type.TypeUtils; 10 | 11 | import java.lang.reflect.Method; 12 | import java.lang.reflect.Parameter; 13 | import java.util.List; 14 | 15 | public class CharacterArgumentConverter implements ArgumentConverter { 16 | 17 | @Override 18 | public Object convert( 19 | List remainingArguments, ImportStack importStack, Context context) { 20 | if (remainingArguments.isEmpty()) { 21 | return null; 22 | } 23 | 24 | Object value = remainingArguments.remove(0); 25 | 26 | // ignore null value 27 | if (null == value || value instanceof SassNull) { 28 | return null; 29 | } 30 | 31 | // value is already in a compatible type 32 | if (TypeUtils.isaCharacter(value.getClass())) { 33 | return value; 34 | } 35 | 36 | if (value instanceof SassString) { 37 | value = ((SassString) value).getValue(); 38 | } 39 | 40 | return value.toString().charAt(0); 41 | } 42 | 43 | @Override 44 | public List argumentSignatures( 45 | Object object, Method method, Parameter parameter, FunctionArgumentSignatureFactory factory 46 | ) { 47 | return factory.createDefaultArgumentSignature(parameter); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/converter/DoubleArgumentConverter.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.converter; 2 | 3 | import io.bit3.jsass.context.Context; 4 | import io.bit3.jsass.context.ImportStack; 5 | import io.bit3.jsass.function.FunctionArgumentSignature; 6 | import io.bit3.jsass.function.FunctionArgumentSignatureFactory; 7 | import io.bit3.jsass.type.SassNull; 8 | import io.bit3.jsass.type.TypeUtils; 9 | 10 | import java.lang.reflect.Method; 11 | import java.lang.reflect.Parameter; 12 | import java.util.List; 13 | 14 | public class DoubleArgumentConverter implements ArgumentConverter { 15 | 16 | @Override 17 | public Object convert( 18 | List remainingArguments, ImportStack importStack, Context context) { 19 | if (remainingArguments.isEmpty()) { 20 | return null; 21 | } 22 | 23 | Object value = remainingArguments.remove(0); 24 | 25 | // ignore null value 26 | if (null == value || value instanceof SassNull) { 27 | return null; 28 | } 29 | 30 | // value is already in a compatible type 31 | if (TypeUtils.isaDouble(value.getClass())) { 32 | return value; 33 | } 34 | 35 | if (value instanceof Number) { 36 | value = ((Number) value).doubleValue(); 37 | } else { 38 | value = Double.parseDouble(value.toString()); 39 | } 40 | 41 | return value; 42 | } 43 | 44 | @Override 45 | public List argumentSignatures( 46 | Object object, Method method, Parameter parameter, FunctionArgumentSignatureFactory factory 47 | ) { 48 | return factory.createDefaultArgumentSignature(parameter); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/transitions/_slide.scss: -------------------------------------------------------------------------------- 1 | /// Creates a sliding transition by translating the element horizontally or vertically. 2 | /// @param {Keyword} $state [in] - State to transition to. 3 | /// @param {Keyword} $direction [left] - Direction to slide to. Can be `up`, `right`, `down`, or `left`. 4 | /// @param {Length} $amount [100%] - Length of the slide as a percentage value. 5 | /// @param {Boolean} $fade [false] - Set to `true` to fade the element in or out simultaneously. 6 | /// @param {Duration} $duration [null] - Length (speed) of the transition. 7 | /// @param {Keyword|Function} $timing [null] - Easing of the transition. 8 | /// @param {Duration} $delay [null] - Delay in seconds or milliseconds before the transition starts. 9 | @mixin mui-slide ( 10 | $state: in, 11 | $direction: left, 12 | $amount: 100%, 13 | $fade: map-get($motion-ui-settings, slide-and-fade), 14 | $duration: null, 15 | $timing: null, 16 | $delay: null 17 | ) { 18 | $slide: slide($state, $direction, $amount); 19 | 20 | // CSS Output 21 | @include transition-start($state) { 22 | @include transition-basics($duration, $timing, $delay); 23 | @include -mui-keyframe-get($slide, 0); 24 | 25 | @if $fade { 26 | transition-property: transform, opacity; 27 | opacity: if($state == in, 0, 1); 28 | } @else { 29 | transition-property: transform, opacity; 30 | } 31 | 32 | backface-visibility: hidden; 33 | } 34 | 35 | @include transition-end($state) { 36 | @include -mui-keyframe-get($slide, 100); 37 | 38 | @if $fade { 39 | opacity: if($state == in, 1, 0); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/components/_progress-bar.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | /// Adds styles for a progress bar container. 6 | @mixin progress-container { 7 | background-color: $progress-background; 8 | height: $progress-height; 9 | margin-bottom: $progress-margin-bottom; 10 | border-radius: $progress-radius; 11 | } 12 | 13 | /// Adds styles for the inner meter of a progress bar. 14 | @mixin progress-meter { 15 | position: relative; 16 | display: block; 17 | width: 0%; 18 | height: 100%; 19 | background-color: $progress-meter-background; 20 | 21 | @if has-value($progress-radius) { 22 | border-radius: $global-radius; 23 | } 24 | } 25 | 26 | /// Adds styles for text in the progress meter. 27 | @mixin progress-meter-text { 28 | @include absolute-center; 29 | position: absolute; 30 | margin: 0; 31 | font-size: 0.75rem; 32 | font-weight: bold; 33 | color: $white; 34 | white-space: nowrap; 35 | 36 | @if has-value($progress-radius) { 37 | border-radius: $progress-radius; 38 | } 39 | } 40 | 41 | @mixin foundation-progress-bar { 42 | // Progress bar 43 | .progress { 44 | @include progress-container; 45 | 46 | @each $name, $color in $foundation-palette { 47 | &.#{$name} { 48 | .progress-meter { 49 | background-color: $color; 50 | } 51 | } 52 | } 53 | } 54 | 55 | // Inner meter 56 | .progress-meter { 57 | @include progress-meter; 58 | } 59 | 60 | // Inner meter text 61 | .progress-meter-text { 62 | @include progress-meter-text; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/util/_transition.scss: -------------------------------------------------------------------------------- 1 | /// Applies basic transition settings to an element. 2 | /// @param {Duration} $duration [null] - Length (speed) of the transition. 3 | /// @param {Keyword|Function} $timing [null] - Easing of the transition. 4 | /// @param {Duration} $delay [null] - Delay in seconds or milliseconds before the transition starts. 5 | @mixin transition-basics( 6 | $duration: null, 7 | $timing: null, 8 | $delay: null 9 | ) { 10 | @include -motion-ui-defaults; 11 | transition-duration: $duration; 12 | transition-timing-function: $timing; 13 | transition-delay: $delay; 14 | } 15 | 16 | /// Wraps the content in the setup class for a transition. 17 | /// @param {Keyword} $dir - State to setup for transition. 18 | @mixin transition-start($dir) { 19 | $selector: -mui-build-selector(map-get($motion-ui-states, $dir)); 20 | 21 | @at-root { 22 | #{$selector} { 23 | @content; 24 | } 25 | } 26 | } 27 | 28 | /// Wraps the content in the active class for a transition. 29 | /// @param {Keyword} $dir - State to activate a transition on. 30 | @mixin transition-end($dir) { 31 | $selector: -mui-build-selector(map-get($motion-ui-states, $dir), true); 32 | 33 | @at-root { 34 | #{$selector} { 35 | @content; 36 | } 37 | } 38 | } 39 | 40 | /// Adds styles for a stagger animation, which can be used with Angular's `ng-repeat`. 41 | /// @param {Duration} $delay-amount - Amount of time in seconds or milliseconds to add between each item's animation. 42 | @mixin stagger($delay-amount) { 43 | transition-delay: $delay-amount; 44 | transition-duration: 0; // Prevent accidental CSS inheritance 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/converter/BooleanArgumentConverter.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.converter; 2 | 3 | import io.bit3.jsass.context.Context; 4 | import io.bit3.jsass.context.ImportStack; 5 | import io.bit3.jsass.function.FunctionArgumentSignature; 6 | import io.bit3.jsass.function.FunctionArgumentSignatureFactory; 7 | import io.bit3.jsass.type.SassBoolean; 8 | import io.bit3.jsass.type.SassNull; 9 | import io.bit3.jsass.type.TypeUtils; 10 | 11 | import java.lang.reflect.Method; 12 | import java.lang.reflect.Parameter; 13 | import java.util.List; 14 | 15 | public class BooleanArgumentConverter implements ArgumentConverter { 16 | 17 | @Override 18 | public Object convert( 19 | List remainingArguments, ImportStack importStack, Context context) { 20 | if (remainingArguments.isEmpty()) { 21 | return null; 22 | } 23 | 24 | Object value = remainingArguments.remove(0); 25 | 26 | // ignore null value 27 | if (null == value || value instanceof SassNull) { 28 | return null; 29 | } 30 | 31 | // value is sass value 32 | if (value instanceof SassBoolean) { 33 | return ((SassBoolean) value).getValue(); 34 | } 35 | 36 | // value is already in a compatible type 37 | if (TypeUtils.isaBoolean(value.getClass())) { 38 | return value; 39 | } 40 | 41 | return Boolean.valueOf(value.toString()); 42 | } 43 | 44 | @Override 45 | public List argumentSignatures( 46 | Object object, Method method, Parameter parameter, FunctionArgumentSignatureFactory factory 47 | ) { 48 | return factory.createDefaultArgumentSignature(parameter); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/scss/app.scss: -------------------------------------------------------------------------------- 1 | @charset 'utf-8'; 2 | 3 | @import 'settings'; 4 | @import 'foundation'; 5 | @import 'motion-ui'; 6 | 7 | @include foundation-global-styles; 8 | @include foundation-grid; 9 | // @include foundation-flex-grid; 10 | @include foundation-typography; 11 | @include foundation-button; 12 | @include foundation-forms; 13 | // @include foundation-range-input; 14 | @include foundation-accordion; 15 | @include foundation-accordion-menu; 16 | @include foundation-badge; 17 | @include foundation-breadcrumbs; 18 | @include foundation-button-group; 19 | @include foundation-callout; 20 | @include foundation-close-button; 21 | @include foundation-menu; 22 | @include foundation-menu-icon; 23 | @include foundation-drilldown-menu; 24 | @include foundation-dropdown; 25 | @include foundation-dropdown-menu; 26 | @include foundation-flex-video; 27 | @include foundation-label; 28 | @include foundation-media-object; 29 | @include foundation-off-canvas; 30 | @include foundation-orbit; 31 | @include foundation-pagination; 32 | @include foundation-progress-bar; 33 | // @include foundation-progress-element; 34 | // @include foundation-meter-element; 35 | @include foundation-slider; 36 | @include foundation-sticky; 37 | @include foundation-reveal; 38 | @include foundation-switch; 39 | @include foundation-table; 40 | @include foundation-tabs; 41 | @include foundation-thumbnail; 42 | @include foundation-title-bar; 43 | @include foundation-tooltip; 44 | @include foundation-top-bar; 45 | @include foundation-visibility-classes; 46 | @include foundation-float-classes; 47 | // @include foundation-flex-classes; 48 | 49 | @include motion-ui-transitions; 50 | @include motion-ui-animations; 51 | -------------------------------------------------------------------------------- /src/test/java/io/bit3/jsass/TestImporter.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass; 2 | 3 | import io.bit3.jsass.importer.Import; 4 | import io.bit3.jsass.importer.Importer; 5 | 6 | import org.apache.commons.io.IOUtils; 7 | 8 | import java.io.IOException; 9 | import java.net.URI; 10 | import java.net.URISyntaxException; 11 | import java.net.URL; 12 | import java.util.Collection; 13 | import java.util.LinkedList; 14 | 15 | public class TestImporter implements Importer { 16 | 17 | @Override 18 | public Collection apply(String url, Import previous) { 19 | if ("functions".equals(url)) { 20 | return new LinkedList<>(); 21 | } 22 | 23 | if ("include".equals(url)) { 24 | // Importers does not support SASS syntax, so we enforce scss here 25 | // String syntax = previous.substring(previous.length() - 4); 26 | String syntax = "scss"; 27 | 28 | String resourcePath = String.format("/%s/src/include.%s", syntax, syntax); 29 | URL resource = getClass().getResource(resourcePath); 30 | 31 | try { 32 | String contents = IOUtils.toString(resource); 33 | 34 | Import importSource = new Import( 35 | new URI(String.format("include.%s", syntax)), 36 | resource.toURI(), 37 | contents 38 | ); 39 | 40 | Collection list = new LinkedList<>(); 41 | list.add(importSource); 42 | return list; 43 | } catch (IOException | URISyntaxException e) { 44 | throw new RuntimeException(e); 45 | } 46 | } 47 | 48 | if ("mixins".equals(url)) { 49 | // ignore 50 | return null; 51 | } 52 | 53 | throw new IllegalArgumentException("Cannot handle import \"" + url + "\""); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/function/arguments/converter/ObjectArgumentConverter.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.function.arguments.converter; 2 | 3 | import io.bit3.jsass.context.Context; 4 | import io.bit3.jsass.context.ImportStack; 5 | import io.bit3.jsass.function.FunctionArgumentSignature; 6 | import io.bit3.jsass.function.FunctionArgumentSignatureFactory; 7 | import io.bit3.jsass.type.SassNull; 8 | 9 | import java.lang.reflect.Method; 10 | import java.lang.reflect.Parameter; 11 | import java.util.List; 12 | 13 | public class ObjectArgumentConverter implements ArgumentConverter { 14 | 15 | private final Class targetType; 16 | 17 | public ObjectArgumentConverter(Class targetType) { 18 | this.targetType = targetType; 19 | } 20 | 21 | @Override 22 | public Object convert( 23 | List remainingArguments, ImportStack importStack, Context context) { 24 | if (remainingArguments.isEmpty()) { 25 | return null; 26 | } 27 | 28 | Object value = remainingArguments.remove(0); 29 | 30 | // ignore null value 31 | if (null == value || value instanceof SassNull) { 32 | return null; 33 | } 34 | 35 | if (targetType.isAssignableFrom(value.getClass())) { 36 | return value; 37 | } 38 | 39 | throw new ConversionException( 40 | String.format( 41 | "Cannot convert SASS type %s to Java type %s", 42 | value.getClass().getName(), 43 | targetType.getName() 44 | ) 45 | ); 46 | } 47 | 48 | @Override 49 | public List argumentSignatures( 50 | Object object, Method method, Parameter parameter, FunctionArgumentSignatureFactory factory 51 | ) { 52 | return factory.createDefaultArgumentSignature(parameter); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/io/bit3/jsass/ExceptionTest.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass; 2 | 3 | import org.junit.jupiter.api.BeforeEach; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.net.URI; 7 | import java.net.URISyntaxException; 8 | import java.net.URL; 9 | 10 | import static org.junit.jupiter.api.Assertions.assertThrows; 11 | 12 | public class ExceptionTest { 13 | 14 | private Compiler compiler; 15 | private Options options; 16 | 17 | /** 18 | * Set up the compiler and the compiler options for each run. 19 | * 20 | * @throws URISyntaxException Throws if the resource URI is invalid. 21 | */ 22 | @BeforeEach 23 | public void setUp() { 24 | compiler = new Compiler(); 25 | options = new Options(); 26 | } 27 | 28 | @Test 29 | public void testExceptionForString() { 30 | assertThrows( 31 | CompilationException.class, 32 | () -> compiler.compileString( 33 | "@error \"Test exception\";", 34 | new URI("/input.scss"), 35 | new URI("/output.css"), 36 | options 37 | ) 38 | ); 39 | } 40 | 41 | @Test 42 | public void testExceptionForSassFile() { 43 | URL inputFile = ExceptionTest.class.getResource("/sass/error.sass"); 44 | 45 | assertThrows( 46 | CompilationException.class, 47 | () -> compiler.compileFile( 48 | inputFile.toURI(), 49 | new URI("/output.css"), 50 | options 51 | ) 52 | ); 53 | } 54 | 55 | @Test 56 | public void testExceptionForScssFile() { 57 | URL inputFile = ExceptionTest.class.getResource("/scss/error.scss"); 58 | 59 | assertThrows( 60 | CompilationException.class, 61 | () -> compiler.compileFile( 62 | inputFile.toURI(), 63 | new URI("/output.css"), 64 | options 65 | ) 66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/components/_flex-video.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group flex-video 7 | //// 8 | 9 | /// Margin below a flex video container. 10 | /// @type Number 11 | $flexvideo-margin-bottom: rem-calc(16) !default; 12 | 13 | /// Padding used to create a 4:3 aspect ratio. 14 | /// @type Number 15 | $flexvideo-ratio: 4 by 3 !default; 16 | 17 | /// Padding used to create a 16:9 aspect ratio. 18 | /// @type Number 19 | $flexvideo-ratio-widescreen: 16 by 9 !default; 20 | 21 | /// Creates a percentage height that can be used as padding in a flex video container. 22 | /// @param {List} $ratio - Ratio to use to calculate the height, formatted as `x by y`. 23 | /// @return {Number} A percentage value that can be used as the `padding-bottom` parameter of a flex video container. 24 | @function flex-video($ratio) { 25 | $w: nth($ratio, 1); 26 | $h: nth($ratio, 3); 27 | @return $h / $w * 100%; 28 | } 29 | 30 | /// Creates a flex video container. 31 | /// @param {List} $ratio [$flexvideo-ratio] - Ratio to use for the container, formatted as `x by y`. 32 | @mixin flex-video($ratio: $flexvideo-ratio) { 33 | position: relative; 34 | height: 0; 35 | padding-bottom: flex-video($ratio); 36 | margin-bottom: $flexvideo-margin-bottom; 37 | overflow: hidden; 38 | 39 | iframe, 40 | object, 41 | embed, 42 | video { 43 | position: absolute; 44 | top: 0; 45 | #{$global-left}: 0; 46 | width: 100%; 47 | height: 100%; 48 | } 49 | } 50 | 51 | @mixin foundation-flex-video { 52 | .flex-video { 53 | @include flex-video; 54 | 55 | &.widescreen { 56 | padding-bottom: flex-video($flexvideo-ratio-widescreen); 57 | } 58 | 59 | &.vimeo { 60 | padding-top: 0; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/type/SassNumber.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.type; 2 | 3 | /** 4 | * A sass number value. 5 | */ 6 | public class SassNumber extends Number implements SassValue { 7 | private static final long serialVersionUID = -6597488416036924788L; 8 | public static final int TYPE = 2; 9 | 10 | /** 11 | * The numeric value. 12 | */ 13 | private double value; 14 | 15 | /** 16 | * The unit. 17 | */ 18 | private String unit; 19 | 20 | /** 21 | * Create a new number. 22 | * 23 | * @param value The numeric value. 24 | * @param unit The unit. 25 | */ 26 | public SassNumber(double value, String unit) { 27 | this.value = value; 28 | this.unit = unit; 29 | } 30 | 31 | /** 32 | * Return the numeric value. 33 | * 34 | * @return The numeric value. 35 | */ 36 | public double getValue() { 37 | return value; 38 | } 39 | 40 | /** 41 | * Set the numeric value. 42 | * 43 | * @param value The numeric value. 44 | */ 45 | public void setValue(double value) { 46 | this.value = value; 47 | } 48 | 49 | /** 50 | * Return the unit. 51 | * 52 | * @return The unit. 53 | */ 54 | public String getUnit() { 55 | return unit; 56 | } 57 | 58 | /** 59 | * Set the unit. 60 | * 61 | * @param unit The unit. 62 | */ 63 | public void setUnit(String unit) { 64 | this.unit = unit; 65 | } 66 | 67 | @Override 68 | public int intValue() { 69 | return (int) value; 70 | } 71 | 72 | @Override 73 | public long longValue() { 74 | return (long) value; 75 | } 76 | 77 | @Override 78 | public float floatValue() { 79 | return (float) value; 80 | } 81 | 82 | @Override 83 | public double doubleValue() { 84 | return value; 85 | } 86 | 87 | @Override 88 | public String toString() { 89 | return super.toString() + unit; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/test/java/io/bit3/jsass/PrecisionTest.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass; 2 | 3 | import org.junit.jupiter.api.BeforeEach; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import static org.hamcrest.CoreMatchers.containsString; 7 | import static org.hamcrest.CoreMatchers.not; 8 | import static org.hamcrest.MatcherAssert.assertThat; 9 | 10 | public class PrecisionTest { 11 | 12 | private static final String scss = ".something {\n" 13 | + " padding: 0 0.8em (5/7) 0.8em;\n" 14 | + "}"; 15 | 16 | Compiler compiler; 17 | Options options; 18 | 19 | /** 20 | * Set up test defaults. 21 | */ 22 | @BeforeEach 23 | public void init() { 24 | compiler = new Compiler(); 25 | options = new Options(); 26 | options.setOutputStyle(OutputStyle.COMPRESSED); 27 | } 28 | 29 | private Output getOutput(int precision) throws CompilationException { 30 | options.setPrecision(precision); 31 | return compiler.compileString(scss, options); 32 | } 33 | 34 | @Test 35 | public void testLowPrecisionOsX() throws CompilationException { 36 | Output output = getOutput(5); 37 | 38 | assertThat(output.getCss(), not(containsString("padding:0 0.8em 0.71429 0.8em"))); 39 | } 40 | 41 | @Test 42 | public void testHighPrecisionOsX() throws CompilationException { 43 | Output output = getOutput(10); 44 | 45 | assertThat(output.getCss(), not(containsString("padding:0 0.8em 0.7142857143 0.8em"))); 46 | } 47 | 48 | @Test 49 | public void testLowPrecisionLinux() throws CompilationException { 50 | Output output = getOutput(5); 51 | 52 | assertThat(output.getCss(), containsString("padding:0 0.8em .71429 0.8em")); 53 | } 54 | 55 | @Test 56 | public void testHighPrecisionLinux() throws CompilationException { 57 | Output output = getOutput(10); 58 | 59 | assertThat(output.getCss(), containsString("padding:0 0.8em .7142857143 0.8em")); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/components/_close-button.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group close-button 7 | //// 8 | 9 | /// Default position of the close button. The first value should be `right` or `left`, and the second value should be `top` or `bottom`. 10 | /// @type List 11 | $closebutton-position: right top !default; 12 | 13 | /// Right (or left) offset for a close button. 14 | /// @type Number 15 | $closebutton-offset-horizontal: 1rem !default; 16 | 17 | /// Top (or bottom) offset for a close button. 18 | /// @type Number 19 | $closebutton-offset-vertical: 0.5rem !default; 20 | 21 | /// Default font size of the close button. 22 | /// @type Number 23 | $closebutton-size: 2em !default; 24 | 25 | /// The line-height of the close button. It affects the spacing of the element. 26 | /// @type Number 27 | $closebutton-lineheight: 1 !default; 28 | 29 | /// Default color of the close button. 30 | /// @type Color 31 | $closebutton-color: $dark-gray !default; 32 | 33 | /// Default color of the close button when being hovered on. 34 | /// @type Color 35 | $closebutton-color-hover: $black !default; 36 | 37 | /// Adds styles for a close button, using the styles in the settings variables. 38 | @mixin close-button { 39 | $x: nth($closebutton-position, 1); 40 | $y: nth($closebutton-position, 2); 41 | 42 | @include disable-mouse-outline; 43 | position: absolute; 44 | color: $closebutton-color; 45 | #{$x}: $closebutton-offset-horizontal; 46 | #{$y}: $closebutton-offset-vertical; 47 | font-size: $closebutton-size; 48 | line-height: $closebutton-lineheight; 49 | cursor: pointer; 50 | 51 | &:hover, 52 | &:focus { 53 | color: $closebutton-color-hover; 54 | } 55 | } 56 | 57 | @mixin foundation-close-button { 58 | .close-button { 59 | @include close-button; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/forms/_select.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group forms 7 | //// 8 | 9 | /// Background color for select menus. 10 | /// @type Color 11 | $select-background: $white !default; 12 | 13 | /// Color of the dropdown triangle inside select menus. Set to `transparent` to remove it entirely. 14 | /// @type Color 15 | $select-triangle-color: $dark-gray !default; 16 | 17 | /// Default radius for select menus. 18 | /// @type Color 19 | $select-radius: $global-radius !default; 20 | 21 | @mixin form-select { 22 | $height: ($input-font-size + ($form-spacing * 1.5) - rem-calc(1)); 23 | 24 | height: $height; 25 | padding: ($form-spacing / 2); 26 | border: $input-border; 27 | margin: 0 0 $form-spacing; 28 | font-size: $input-font-size; 29 | font-family: $input-font-family; 30 | line-height: normal; 31 | color: $input-color; 32 | background-color: $select-background; 33 | border-radius: $select-radius; 34 | -webkit-appearance: none; 35 | -moz-appearance: none; 36 | 37 | @if $select-triangle-color != transparent { 38 | @include background-triangle($select-triangle-color); 39 | background-size: 9px 6px; 40 | background-position: $global-right (-$form-spacing) center; 41 | background-origin: content-box; 42 | background-repeat: no-repeat; 43 | padding-#{$global-right}: ($form-spacing * 1.5); 44 | } 45 | 46 | // Disabled state 47 | &:disabled { 48 | background-color: $input-background-disabled; 49 | cursor: $input-cursor-disabled; 50 | } 51 | 52 | // Hide the dropdown arrow shown in newer IE versions 53 | &::-ms-expand { 54 | display: none; 55 | } 56 | 57 | &[multiple] { 58 | height: auto; 59 | background-image: none; 60 | } 61 | } 62 | 63 | @mixin foundation-form-select { 64 | select { 65 | @include form-select; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/transitions/_hinge.scss: -------------------------------------------------------------------------------- 1 | /// Creates a hinge transition by rotating the element. 2 | /// @param {Keyword} $state [in] - State to transition to. 3 | /// @param {Keyword} $from [left] - Edge of the element to rotate from. Can be `top`, `right`, `bottom`, or `left`. 4 | /// @param {Keyword} $axis [edge] - Axis of the element to rotate on. Can be `edge` or `center`. 5 | /// @param {Length} $perspective [2000px] - Perceived distance between the viewer and the element. A higher number will make the rotation effect more pronounced. 6 | /// @param {Keyword} $turn-origin [from-back] - Side of the element to start the rotation from. Can be `from-back` or `from-front`. 7 | /// @param {Boolean} $fade [true] - Set to `true` to fade the element in or out simultaneously. 8 | /// @param {Duration} $duration [null] - Length (speed) of the transition. 9 | /// @param {Keyword|Function} $timing [null] - Easing of the transition. 10 | /// @param {Duration} $delay [null] - Delay in seconds or milliseconds before the transition starts. 11 | @mixin mui-hinge ( 12 | $state: in, 13 | $from: left, 14 | $axis: edge, 15 | $perspective: 2000px, 16 | $turn-origin: from-back, 17 | $fade: map-get($motion-ui-settings, hinge-and-fade), 18 | $duration: null, 19 | $timing: null, 20 | $delay: null 21 | ) { 22 | $hinge: hinge($state, $from, $axis, $perspective, $turn-origin); 23 | 24 | @include transition-start($state) { 25 | @include transition-basics($duration, $timing, $delay); 26 | @include -mui-keyframe-get($hinge, 0); 27 | 28 | @if $fade { 29 | transition-property: transform, opacity; 30 | opacity: if($state == in, 0, 1); 31 | } @else { 32 | transition-property: transform, opacity; 33 | } 34 | } 35 | 36 | @include transition-end($state) { 37 | @include -mui-keyframe-get($hinge, 100); 38 | 39 | @if $fade { 40 | opacity: if($state == in, 1, 0); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /bin/make-libjsass-linux-armhf32-local.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo 4 | echo -e "\e[91m+-------------------------------------------------------------------------+\e[0m" 5 | echo -e "\e[91m| |\e[0m" 6 | echo -e "\e[91m| !!! Attention !!! This file is intended for local development only! |\e[0m" 7 | echo -e "\e[91m| |\e[0m" 8 | echo -e "\e[91m+-------------------------------------------------------------------------+\e[0m" 9 | echo 10 | 11 | set -xeuo pipefail 12 | 13 | BASE_DIR=$(dirname $(dirname $(realpath "$0"))) 14 | 15 | cd "$BASE_DIR/src/main" 16 | 17 | rm -fr resources/armhf32 18 | mkdir -p resources/armhf32 19 | 20 | # *** Build libsass 21 | 22 | make -C libsass clean 23 | cd libsass 24 | git reset --hard # hard reset 25 | git clean -xdf # hard clean 26 | cd .. 27 | 28 | # We use: 29 | # CC=arm-linux-gnueabihf-gcc 30 | # CXX=arm-linux-gnueabihf-g++ 31 | # WINDRES=arm-linux-gnueabihf-gcc-ar 32 | # BUILD="static" to make sure that we build a static library 33 | CFLAGS="-Wall" \ 34 | CXXFLAGS="-Wall" \ 35 | LDFLAGS="-stdlib=libc++" \ 36 | CC=arm-linux-gnueabihf-gcc \ 37 | CXX=arm-linux-gnueabihf-g++ \ 38 | AR=arm-linux-gnueabihf-gcc-ar \ 39 | BUILD=static \ 40 | make -C libsass -j4 41 | 42 | # *** Build libjsass 43 | 44 | rm -fr c/build 45 | mkdir -p c/build 46 | cd c/build 47 | cmake -DCMAKE_TOOLCHAIN_FILE=/$BASE_DIR/src/main/c/Toolchain-linux-armhf32.cmake ../ 48 | make 49 | cp libjsass.so ../../resources/linux-armhf32/libjsass.so 50 | 51 | # *** Build libjsass_test 52 | 53 | cd "$BASE_DIR/src/test" 54 | 55 | rm -fr resources/armhf32 56 | mkdir -p resources/armhf32 57 | 58 | rm -fr c/build 59 | mkdir -p c/build 60 | cd c/build 61 | cmake -DCMAKE_TOOLCHAIN_FILE=/$BASE_DIR/src/main/c/Toolchain-linux-armhf32.cmake ../ 62 | make 63 | cp libjsass_test.so ../../resources/linux-armhf32/libjsass_test.so 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![pipeline status](https://gitlab.com/jsass/jsass/badges/main/pipeline.svg)](https://gitlab.com/jsass/jsass/commits/main) 2 | [![Build Status](https://cloud.drone.io/api/badges/bit3/jsass/status.svg)](https://cloud.drone.io/bit3/jsass) 3 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/bit3/jsass/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/bit3/jsass/?branch=master) 4 | [![Code Coverage](https://scrutinizer-ci.com/g/bit3/jsass/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/bit3/jsass/?branch=master) 5 | [![Known Vulnerabilities](https://snyk.io/test/github/bit3/jsass/badge.svg)](https://snyk.io/test/github/bit3/jsass) 6 | 7 | # Java sass compiler 8 | 9 | Feature complete java sass compiler. 10 | 11 | ## Documentation 12 | 13 | - Read the [official documentation](https://jsass.gitlab.io/). 14 | - Check out the [example webapp](./example). 15 | - Inspect the [API documentation](https://javadoc.io/doc/io.bit3/jsass/). 16 | 17 | ## CVE-2022-42889 18 | 19 | In October 2022, a critical vulnerability in the commons-text library became known ([CVE-2022-42889](https://securitylab.github.com/advisories/GHSL-2022-018_Apache_Commons_Text/)). jsass uses the commons-text library, but not the affected StringSubstitutor class! 20 | Thus, jsass is not directly affected by this vulnerability. 21 | However, in Jsass version 5.10.5, the commons-text dependency has been updated to version 1.10.0. 22 | 23 | ## Developers 24 | 25 | ### Gradle tasks you should know 26 | 27 | `gradle check` runs checkstyle, pmd, junit locally. 28 | 29 | `gradle buildNativeLibs` build the native libs, using our build docker container. 30 | 31 | ### How to make a release 32 | 33 | ```bash 34 | $ ./gradlew clean release 35 | $ git checkout $(git describe --abbrev=0) 36 | $ ./gradlew clean signMavenPublication publishAllPublicationsToMavenCentralRepository 37 | ``` 38 | 39 | Don't forget to release the artifact from [staging repository](https://oss.sonatype.org/#stagingRepositories)! 40 | 41 | ## License 42 | 43 | MIT-License 44 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/grid/_grid.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group grid 7 | //// 8 | 9 | /// The maximum width of a row. 10 | /// @type Number 11 | $grid-row-width: $global-width !default; 12 | 13 | /// The default column count of a grid. Changing this value affects the logic of the grid mixins, and the number of CSS classes output. 14 | /// @type Number 15 | $grid-column-count: 12 !default; 16 | 17 | /// The amount of space between columns at different screen sizes. To use just one size, set the variable to a number instead of a map. 18 | /// @type Map | Length 19 | /// @since 6.1.0 20 | $grid-column-gutter: ( 21 | small: 20px, 22 | medium: 30px, 23 | ) !default; 24 | 25 | /// If `true`, the last column in a row will align to the opposite edge of the row. 26 | /// @type Boolean 27 | $grid-column-align-edge: true !default; 28 | 29 | /// The highest number of `.x-up` classes available when using the block grid CSS. 30 | /// @type Number 31 | $block-grid-max: 8 !default; 32 | 33 | // Internal value to store the end column float direction 34 | $-zf-end-float: if($grid-column-align-edge, $global-right, $global-left); 35 | 36 | // The last piece to transition the responsive gutter feature 37 | // Remove this in 6.3 38 | $grid-column-responsive-gutter: null !default; 39 | @if $grid-column-responsive-gutter { 40 | // scss-lint:disable DebugStatement 41 | @warn 'Rename $grid-column-responsive-gutter to $grid-column-gutter to remove this warning.'; 42 | $grid-column-gutter: $grid-column-responsive-gutter; 43 | } 44 | 45 | // If a single value is passed as a gutter, convert it to a map so the code knows what to do with it 46 | @if type-of($grid-column-gutter) == 'number' { 47 | $grid-column-gutter: ( 48 | small: $grid-column-gutter, 49 | ); 50 | } 51 | 52 | @import 'row'; 53 | @import 'column'; 54 | @import 'size'; 55 | @import 'position'; 56 | @import 'gutter'; 57 | @import 'classes'; 58 | @import 'layout'; 59 | 60 | @import 'flex-grid'; 61 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/motion-ui/util/_series.scss: -------------------------------------------------------------------------------- 1 | $-mui-queue: (); 2 | 3 | /// Pauses the animation on an element by default, and then plays it when an active class is added to a parent. Also sets the fill mode of the animation to `both`. This pauses the element at the first frame of the animation, and holds it in place at the end. 4 | /// @access private 5 | %animated-element { 6 | animation-play-state: paused; 7 | animation-fill-mode: both; 8 | 9 | .#{map-get($motion-ui-settings, activate-queue-class)} & { 10 | animation-play-state: running; 11 | } 12 | } 13 | 14 | /// Creates a new animation queue. 15 | /// @param {Duration} $delay [0s] - Delay in seconds or milliseconds to place at the front of the animation queue. 16 | @mixin mui-series($delay: 0s) { 17 | $-mui-queue: () !global; 18 | 19 | @if $delay > 0 { 20 | $item: ($delay, 0s); 21 | $-mui-queue: append($-mui-queue, $item) !global; 22 | } 23 | 24 | @content; 25 | } 26 | 27 | /// Adds an animation to an animation queue. Only use this mixin inside of `mui-series()`. 28 | /// @param {Duration} $duration [1s] - Length of the animation. 29 | /// @param {Duration} $gap [0s] - Amount of time to pause before playing the animation after this one. Use a negative value to make the next effect overlap with the current one. 30 | /// @param {Function} $keyframes... - One or more effect functions to build the keyframe with. 31 | @mixin mui-queue( 32 | $duration: 1s, 33 | $gap: 0s, 34 | $keyframes... 35 | ) { 36 | // Build the animation 37 | $kf: -mui-process-args($keyframes...); 38 | 39 | // Calculate the delay for this animation based on how long the previous ones take 40 | $actual-delay: 0s; 41 | @each $anim in $-mui-queue { 42 | $actual-delay: $actual-delay + nth($anim, 1) + nth($anim, 2); 43 | } 44 | 45 | // Append this animation's length and gap to the end of the queue 46 | $item: ($duration, $gap); 47 | $-mui-queue: append($-mui-queue, $item) !global; 48 | 49 | // CSS output 50 | @extend %animated-element; 51 | @include mui-animation($kf); 52 | animation-duration: $duration; 53 | animation-delay: $actual-delay; 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/io/bit3/jsass/adapter/NativeOptions.java: -------------------------------------------------------------------------------- 1 | package io.bit3.jsass.adapter; 2 | 3 | import io.bit3.jsass.function.FunctionWrapper; 4 | 5 | class NativeOptions { 6 | public final FunctionWrapper[] functions; 7 | 8 | public final NativeImporterWrapper[] headerImporters; 9 | 10 | public final NativeImporterWrapper[] importers; 11 | 12 | public final String includePath; 13 | 14 | public final String indent; 15 | 16 | public final boolean isIndentedSyntaxSrc; 17 | 18 | public final String linefeed; 19 | 20 | public final boolean omitSourceMapUrl; 21 | 22 | public final int outputStyle; 23 | 24 | public final String pluginPath; 25 | 26 | public final int precision; 27 | 28 | public final boolean sourceComments; 29 | 30 | public final boolean sourceMapContents; 31 | 32 | public final boolean sourceMapEmbed; 33 | 34 | public final String sourceMapFile; 35 | 36 | public final String sourceMapRoot; 37 | 38 | NativeOptions( 39 | FunctionWrapper[] functions, 40 | NativeImporterWrapper[] headerImporters, 41 | NativeImporterWrapper[] importers, 42 | String includePath, 43 | String indent, 44 | boolean isIndentedSyntaxSrc, 45 | String linefeed, 46 | boolean omitSourceMapUrl, 47 | int outputStyle, 48 | String pluginPath, 49 | int precision, 50 | boolean sourceComments, 51 | boolean sourceMapContents, 52 | boolean sourceMapEmbed, 53 | String sourceMapFile, 54 | String sourceMapRoot 55 | ) { 56 | this.functions = functions; 57 | this.headerImporters = headerImporters; 58 | this.importers = importers; 59 | this.includePath = includePath; 60 | this.indent = indent; 61 | this.isIndentedSyntaxSrc = isIndentedSyntaxSrc; 62 | this.linefeed = linefeed; 63 | this.omitSourceMapUrl = omitSourceMapUrl; 64 | this.outputStyle = outputStyle; 65 | this.pluginPath = pluginPath; 66 | this.precision = precision; 67 | this.sourceComments = sourceComments; 68 | this.sourceMapContents = sourceMapContents; 69 | this.sourceMapEmbed = sourceMapEmbed; 70 | this.sourceMapFile = sourceMapFile; 71 | this.sourceMapRoot = sourceMapRoot; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/typography/_helpers.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group typography-helpers 7 | //// 8 | 9 | /// Default font size for lead paragraphs. 10 | /// @type Number 11 | $lead-font-size: $global-font-size * 1.25 !default; 12 | 13 | /// Default line height for lead paragraphs. 14 | /// @type String 15 | $lead-lineheight: 1.6 !default; 16 | 17 | /// Default line height for subheaders. 18 | /// @type Number 19 | $subheader-lineheight: 1.4 !default; 20 | 21 | /// Default font color for subheaders. 22 | /// @type Color 23 | $subheader-color: $dark-gray !default; 24 | 25 | /// Default font weight for subheaders. 26 | /// @type String 27 | $subheader-font-weight: $global-weight-normal !default; 28 | 29 | /// Default top margin for subhheaders. 30 | /// @type Number 31 | $subheader-margin-top: 0.2rem !default; 32 | 33 | /// Default bottom margin for subheaders. 34 | /// @type Number 35 | $subheader-margin-bottom: 0.5rem !default; 36 | 37 | /// Default font size for statistic numbers. 38 | /// @type Number 39 | $stat-font-size: 2.5rem !default; 40 | 41 | @mixin foundation-typography-helpers { 42 | // Use to create a subheading under a main header 43 | // Make sure you pair the two elements in a
element, like this: 44 | //
45 | //

Heading

46 | //

Subheading

47 | //
48 | .subheader { 49 | margin-top: $subheader-margin-top; 50 | margin-bottom: $subheader-margin-bottom; 51 | font-weight: $subheader-font-weight; 52 | line-height: $subheader-lineheight; 53 | color: $subheader-color; 54 | } 55 | 56 | // Use to style an introductory lead, deck, blurb, etc. 57 | .lead { 58 | font-size: $lead-font-size; 59 | line-height: $lead-lineheight; 60 | } 61 | 62 | // Use to style a large number to display a statistic 63 | .stat { 64 | font-size: $stat-font-size; 65 | line-height: 1; 66 | 67 | p + & { 68 | margin-top: -1rem; 69 | } 70 | } 71 | 72 | // Use to remove the bullets from an unordered list 73 | .no-bullet { 74 | margin-#{$global-left}: 0; 75 | list-style: none; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/components/_title-bar.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group title-bar 7 | //// 8 | 9 | /// Background color of a title bar. 10 | /// @type Color 11 | $titlebar-background: $black !default; 12 | 13 | /// Color of text inside a title bar. 14 | /// @type Color 15 | $titlebar-color: $white !default; 16 | 17 | /// Padding inside a title bar. 18 | /// @type Length 19 | $titlebar-padding: 0.5rem !default; 20 | 21 | /// Font weight of text inside a title bar. 22 | /// @type Weight 23 | $titlebar-text-font-weight: bold !default; 24 | 25 | /// Color of menu icons inside a title bar. 26 | /// @type Color 27 | $titlebar-icon-color: $white !default; 28 | 29 | /// Color of menu icons inside a title bar on hover. 30 | /// @type Color 31 | $titlebar-icon-color-hover: $medium-gray !default; 32 | 33 | /// Spacing between the menu icon and text inside a title bar. 34 | /// @type Length 35 | $titlebar-icon-spacing: 0.25rem !default; 36 | 37 | @mixin foundation-title-bar { 38 | .title-bar { 39 | background: $titlebar-background; 40 | color: $titlebar-color; 41 | padding: $titlebar-padding; 42 | 43 | @if $global-flexbox { 44 | display: flex; 45 | align-items: center; 46 | justify-content: space-between; 47 | } 48 | @else { 49 | @include clearfix; 50 | } 51 | 52 | .menu-icon { 53 | margin-#{$global-left}: $titlebar-icon-spacing; 54 | margin-#{$global-right}: $titlebar-icon-spacing; 55 | } 56 | } 57 | 58 | @if $global-flexbox { 59 | // scss-lint:disable ZeroUnit 60 | .title-bar-left, 61 | .title-bar-right { 62 | flex: 1 1 0px; 63 | } 64 | 65 | .title-bar-right { 66 | text-align: right; 67 | } 68 | } 69 | @else { 70 | .title-bar-left { 71 | float: left; 72 | } 73 | 74 | .title-bar-right { 75 | float: right; 76 | text-align: right; 77 | } 78 | } 79 | 80 | .title-bar-title { 81 | font-weight: $titlebar-text-font-weight; 82 | vertical-align: middle; 83 | display: inline-block; 84 | } 85 | 86 | .menu-icon.dark { 87 | @include hamburger; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/forms/_progress.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group progress-bar 7 | //// 8 | 9 | /// Height of a progress bar. 10 | /// @type Number 11 | $progress-height: 1rem !default; 12 | 13 | /// Background color of a progress bar. 14 | /// @type Color 15 | $progress-background: $medium-gray !default; 16 | 17 | /// Bottom margin of a progress bar. 18 | /// @type Number 19 | $progress-margin-bottom: $global-margin !default; 20 | 21 | /// Default color of a progress bar's meter. 22 | /// @type Color 23 | $progress-meter-background: $primary-color !default; 24 | 25 | /// Default radius of a progress bar. 26 | /// @type Number 27 | $progress-radius: $global-radius !default; 28 | 29 | @mixin foundation-progress-element { 30 | progress { 31 | -webkit-appearance: none; 32 | -moz-appearance: none; 33 | display: block; 34 | width: 100%; 35 | height: $progress-height; 36 | margin-bottom: $progress-margin-bottom; 37 | 38 | @if hasvalue($progress-radius) { 39 | border-radius: $progress-radius; 40 | } 41 | 42 | // For Firefox 43 | background: $progress-background; 44 | border: 0; 45 | 46 | &::-webkit-progress-bar { 47 | background: $progress-background; 48 | 49 | @if hasvalue($progress-radius) { 50 | border-radius: $progress-radius; 51 | } 52 | } 53 | 54 | &::-webkit-progress-value { 55 | background: $progress-meter-background; 56 | 57 | @if hasvalue($progress-radius) { 58 | border-radius: $progress-radius; 59 | } 60 | } 61 | 62 | &::-moz-progress-bar { 63 | background: $progress-meter-background; 64 | 65 | @if hasvalue($progress-radius) { 66 | border-radius: $progress-radius; 67 | } 68 | } 69 | 70 | @each $name, $color in $foundation-palette { 71 | &.#{$name} { 72 | // Internet Explorer sets the fill with color 73 | color: $color; 74 | 75 | &::-webkit-progress-value { 76 | background: $color; 77 | } 78 | 79 | &::-moz-progress-bar { 80 | background: $color; 81 | } 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/test/c/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(jsass) 3 | 4 | set(SOURCE_FILES io_bit3_jsass_adapter_NativeTestAdapter.c empty.cpp) 5 | 6 | include_directories( 7 | # apple 8 | "/System/Library/Frameworks/JavaVM.framework/Headers" 9 | 10 | # osxcross 11 | "/osxcross/include/tapi" 12 | "/osxcross/include/xar" 13 | "/usr/include/clang/14/include/" 14 | 15 | # unix 16 | "/usr/lib/jvm/java/include" 17 | "/usr/lib/jvm/java/include/linux" 18 | "/usr/lib/jvm/default/include" 19 | "/usr/lib/jvm/default/include/linux" 20 | "/usr/lib/jvm/default-java/include" 21 | "/usr/lib/jvm/default-java/include/linux" 22 | "/usr/lib/jvm/java-8-openjdk-amd64/include" 23 | "/usr/lib/jvm/java-8-openjdk-amd64/include/linux" 24 | "/usr/lib/jvm/java-8-oracle/include" 25 | "/usr/lib/jvm/java-8-oracle/include/linux" 26 | 27 | # custom installation 28 | "/opt/java8/include" 29 | "/opt/java8/include/linux" 30 | "/opt/java11/include" 31 | "/opt/java11/include/linux" 32 | "/opt/java17/include" 33 | "/opt/java17/include/linux" 34 | "/opt/java21/include" 35 | "/opt/java21/include/linux" 36 | 37 | # libsass 38 | "../../main/libsass/include" 39 | 40 | # jsass 41 | "../../main/c" 42 | ) 43 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") 44 | 45 | message("search for libsass static library in: ${CMAKE_SOURCE_DIR}/../../main/libsass/lib") 46 | find_library(SASS_EXT_LIBRARY NAMES sass libsass PATHS "${CMAKE_SOURCE_DIR}/../../main/libsass/lib" NO_DEFAULT_PATH) 47 | message(STATUS "libsass library: ${SASS_EXT_LIBRARY}") 48 | add_library(sass STATIC IMPORTED) 49 | set_property(TARGET sass PROPERTY IMPORTED_LOCATION "${SASS_EXT_LIBRARY}") 50 | 51 | file(WRITE empty.cpp "") 52 | 53 | add_library(jsass_test SHARED ${SOURCE_FILES}) 54 | set_property(TARGET jsass_test PROPERTY C_STANDARD 99) 55 | 56 | set(LINK_FLAGS ${LINK_FLAGS} -static-libgcc -static-libstdc++ "-Wl,--no-whole-archive") 57 | 58 | if(APPLE) 59 | target_link_libraries(jsass_test PUBLIC sass "-exported_symbols_list ${CMAKE_SOURCE_DIR}/../../main/c/exported_symbols_list.txt") 60 | else() 61 | target_link_libraries(jsass_test PUBLIC sass "-Wl,--version-script=${CMAKE_SOURCE_DIR}/../../main/c/version_script.map") 62 | endif() 63 | -------------------------------------------------------------------------------- /example/webapp/src/main/webapp/WEB-INF/assets/foundation/components/_drilldown.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites by ZURB 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | //// 6 | /// @group drilldown 7 | //// 8 | 9 | /// Transition property to use for animating menus. 10 | /// @type Transition 11 | $drilldown-transition: transform 0.15s linear !default; 12 | 13 | /// Adds arrows to drilldown items with submenus, as well as the back button. 14 | /// @type Boolean 15 | $drilldown-arrows: true !default; 16 | 17 | /// Sets drilldown arrow color if arrow is used. 18 | /// @type Color 19 | $drilldown-arrow-color: $primary-color !default; 20 | 21 | /// Background color for drilldown submenus. 22 | /// @type Color 23 | $drilldown-background: $white !default; 24 | 25 | @mixin foundation-drilldown-menu { 26 | // Applied to the Menu container 27 | .is-drilldown { 28 | position: relative; 29 | overflow: hidden; 30 | 31 | li { 32 | display: block !important; 33 | } 34 | } 35 | 36 | // Applied to nested