diff --git a/.gitignore b/.gitignore index 23ea15c..b512c09 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1 @@ -node_modules -tmp -.sass-cache -*.gem -npm-debug.log -.sassdoc -sassdocify +node_modules \ No newline at end of file diff --git a/.npmignore b/.npmignore deleted file mode 100644 index f8b0980..0000000 --- a/.npmignore +++ /dev/null @@ -1,6 +0,0 @@ -node_modules -tmp -dist -.* -sache.json -.gemspec \ No newline at end of file diff --git a/.sassdocrc b/.sassdocrc deleted file mode 100644 index b1bda79..0000000 --- a/.sassdocrc +++ /dev/null @@ -1,10 +0,0 @@ -basePath: "https://github.com/HugoGiraudel/SassyJSON/tree/master/stylesheets" -display: - access: ["public"] - alias: false - watermark: true - -package: "./package.json" -theme: "default" -groups: - undefined: "General" diff --git a/.scss-lint.yml b/.scss-lint.yml new file mode 100644 index 0000000..ddc42a0 --- /dev/null +++ b/.scss-lint.yml @@ -0,0 +1,233 @@ +linters: + BangFormat: + enabled: true + space_before_bang: true + space_after_bang: false + + BemDepth: + enabled: false + max_elements: 1 + + BorderZero: + enabled: true + convention: zero # or `none` + + ChainedClasses: + enabled: false + + ColorKeyword: + enabled: false + + ColorVariable: + enabled: false + + Comment: + enabled: true + style: silent + + DebugStatement: + enabled: true + + DeclarationOrder: + enabled: true + + DisableLinterReason: + enabled: false + + DuplicateProperty: + enabled: true + + ElsePlacement: + enabled: true + style: same_line # or 'new_line' + + EmptyLineBetweenBlocks: + enabled: true + ignore_single_line_blocks: true + + EmptyRule: + enabled: true + + ExtendDirective: + enabled: false + + FinalNewline: + enabled: true + present: false + + HexLength: + enabled: false + style: long # or 'long' + + HexNotation: + enabled: true + style: lowercase # or 'uppercase' + + HexValidation: + enabled: true + + IdSelector: + enabled: true + + ImportantRule: + enabled: true + + ImportPath: + enabled: true + leading_underscore: false + filename_extension: false + + Indentation: + enabled: true + allow_non_nested_indentation: false + character: space # or 'tab' + width: 4 + + LeadingZero: + enabled: true + style: include_zero # or 'include_zero' + + MergeableSelector: + enabled: true + force_nesting: true + + NameFormat: + enabled: true + allow_leading_underscore: true + convention: hyphenated_lowercase # or 'camel_case', or 'snake_case', or a regex pattern + + NestingDepth: + enabled: true + max_depth: 3 + ignore_parent_selectors: false + + PlaceholderInExtend: + enabled: false + + PropertyCount: + enabled: false + include_nested: false + max_properties: 10 + + PropertySortOrder: + enabled: true + ignore_unspecified: false + min_properties: 2 + separate_groups: false + + PropertySpelling: + enabled: true + extra_properties: [] + disabled_properties: [] + + PropertyUnits: + enabled: true + global: [ + 'ch', 'em', 'ex', 'rem', # Font-relative lengths + 'cm', 'in', 'mm', 'pc', 'pt', 'px', 'q', # Absolute lengths + 'vh', 'vw', 'vmin', 'vmax', # Viewport-percentage lengths + 'deg', 'grad', 'rad', 'turn', # Angle + 'ms', 's', # Duration + 'Hz', 'kHz', # Frequency + 'dpi', 'dpcm', 'dppx', # Resolution + '%'] # Other + properties: {} + + PseudoElement: + enabled: true + + QualifyingElement: + enabled: true + allow_element_with_attribute: false + allow_element_with_class: false + allow_element_with_id: false + + SelectorDepth: + enabled: true + max_depth: 3 + + SelectorFormat: + enabled: true + convention: hyphenated_lowercase # or 'strict_BEM', or 'hyphenated_BEM', or 'snake_case', or 'camel_case', or a regex pattern + + Shorthand: + enabled: true + allowed_shorthands: [1, 2, 3] + + SingleLinePerProperty: + enabled: true + allow_single_line_rule_sets: true + + SingleLinePerSelector: + enabled: true + + SpaceAfterComma: + enabled: true + style: one_space # or 'no_space', or 'at_least_one_space' + + SpaceAfterPropertyColon: + enabled: true + style: one_space # or 'no_space', or 'at_least_one_space', or 'aligned' + + SpaceAfterPropertyName: + enabled: true + + SpaceAfterVariableName: + enabled: false + + SpaceAroundOperator: + enabled: true + style: one_space # or 'at_least_one_space', or 'no_space' + + SpaceBeforeBrace: + enabled: true + style: space # or 'new_line' + allow_single_line_padding: false + + SpaceBetweenParens: + enabled: false + spaces: 0 + + StringQuotes: + enabled: true + style: single_quotes # or double_quotes + + TrailingSemicolon: + enabled: true + + TrailingWhitespace: + enabled: true + + TrailingZero: + enabled: false + + TransitionAll: + enabled: false + + UnnecessaryMantissa: + enabled: true + + UnnecessaryParentReference: + enabled: true + + UrlFormat: + enabled: true + + UrlQuotes: + enabled: true + + VariableForProperty: + enabled: false + properties: [] + + VendorPrefix: + enabled: true + identifier_list: base + additional_identifiers: [] + excluded_identifiers: [] + + ZeroUnit: + enabled: true + + Compass::*: + enabled: false \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 293a4a3..c51b457 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,11 @@ language: node_js -branches: - only: - - master -git: - depth: 1 node_js: - - '0.10' -env: - - SASS_VERSION=3.3.4 -before_script: - - gem update --system - - gem install sass -v $SASS_VERSION - - gem install scss-lint - - npm install -g grunt-cli + - "4.4" +before_install: + - rvm install 2.2.2 + - gem install sass + - gem install scss-lint + - npm install -g grunt-cli +install: npm install +before_script: + - grunt compile \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 4abe87a..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,24 +0,0 @@ -# Changelog -* `1.1.8`: Solved an issue with tabs -* `1.1.7`: Included cosmetic changes made after linting with [scss-lint](https://github.com/causes/scss-lint) -* `1.1.6`: JSON files that are loaded via `@import "data.json?varname` can be pretty printed now. -* `1.1.5`: Fixed `json-encode` mixin to keep `body::before` in the render tree. Making it possible to access via `getComputedStyle(document.body, ':before')` -* `1.1.4`: Small fix for the `npm` release -* `1.1.3`: fixed error in `_pow` introduced after updating to Sass 3.3.0.rc.3 -* `1.1.2`: Made it possible to import JSON files via `@import 'relative/path/to/file.json?variable-name'` -* `1.1.1`: fixing a minor issue with the gem -* `1.1.0`: adding the ability to import a JSON file -* `1.0.11`: fixing an issue with scientific number parsing -* `1.0.10`: improving number and string helpers -* `1.0.9`: fixing a bug in `_find-exponent` -* `1.0.8`: fixing a major issue in Ruby Gem -* `1.0.7`: minor fixes and stable Ruby Gem -* `1.0.6`: released a Ruby Gem -* `1.0.5`: improved the encoding mixin -* `1.0.4`: fixed an error in map parsing -* `1.0.3`: slightly edited the mixin to dump JSON to CSS -* `1.0.2`: fixed an issue with string parsing -* `1.0.1`: fixed an issue with alpha color parsing -* `1.0.0`: Stable API. `json-encode` and `json-decode` -* `0.0.2`: added `json-decode` and test -* `0.0.1`: initial commit diff --git a/Gruntfile.js b/Gruntfile.js index f9b85eb..33e1012 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,177 +1,141 @@ -module.exports = function(grunt) { - - // Modules - grunt.loadNpmTasks('grunt-contrib-sass'); - grunt.loadNpmTasks('grunt-contrib-watch'); - grunt.loadNpmTasks('grunt-contrib-concat'); - grunt.loadNpmTasks('grunt-scsslint'); - grunt.loadNpmTasks('bootcamp'); - - // Grunt Tasks - grunt.initConfig({ - dir : { - src : 'stylesheets', - dist : 'dist' - }, - pkg: grunt.file.readJSON('package.json'), +/****************************************************************** + * Sass-JSON + * Grunt Setup + * @uthor [@esr360](http://twitter.com/esr360) + ******************************************************************/ - concat: { - options: { - banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %> */\n', - }, - dist: { - src: [ - // Decoder - '<%= dir.src %>/decode/helpers/all/_throw.scss', - '<%= dir.src %>/decode/helpers/all/_value.scss', - '<%= dir.src %>/decode/helpers/map/_consume.scss', - '<%= dir.src %>/decode/helpers/string/_find-ending-quote.scss', - '<%= dir.src %>/decode/helpers/string/_strip-token.scss', - '<%= dir.src %>/decode/helpers/string/_length.scss', - '<%= dir.src %>/decode/helpers/color/_color.scss', - '<%= dir.src %>/decode/helpers/color/_get-color-value.scss', - '<%= dir.src %>/decode/helpers/color/_hsl.scss', - '<%= dir.src %>/decode/helpers/color/_rgb.scss', - '<%= dir.src %>/decode/helpers/color/_hex.scss', - '<%= dir.src %>/decode/helpers/color/_hex-to-dec.scss', - '<%= dir.src %>/decode/helpers/number/_pow.scss', - '<%= dir.src %>/decode/helpers/number/_find-integer.scss', - '<%= dir.src %>/decode/helpers/number/_find-digits.scss', - '<%= dir.src %>/decode/helpers/number/_find-exponent.scss', - '<%= dir.src %>/decode/types/_string.scss', - '<%= dir.src %>/decode/types/_bool.scss', - '<%= dir.src %>/decode/types/_null.scss', - '<%= dir.src %>/decode/types/_number.scss', - '<%= dir.src %>/decode/types/_list.scss', - '<%= dir.src %>/decode/types/_map.scss', - '<%= dir.src %>/decode/api/_json.scss', +module.exports = function(grunt) { + + grunt.initConfig({ + + pkg: grunt.file.readJSON('package.json'), + + /** + * Clean + * @see https://github.com/gruntjs/grunt-contrib-clean + */ + clean: { + dist: { + src: 'dist' + } + }, + + /** + * Concat + * @see https://github.com/gruntjs/grunt-contrib-concat + */ + concat: { + scss: { + src: [ + 'src/api/*.scss', + 'src/helpers/*.scss', + 'src/mixins/*.scss', + 'src/types/*.scss' + ], + dest: 'dist/_sass-json.scss', + } + }, - // Encoder - '<%= dir.src %>/encode/helpers/_quote.scss', - '<%= dir.src %>/encode/types/_bool.scss', - '<%= dir.src %>/encode/types/_color.scss', - '<%= dir.src %>/encode/types/_list.scss', - '<%= dir.src %>/encode/types/_map.scss', - '<%= dir.src %>/encode/types/_number.scss', - '<%= dir.src %>/encode/types/_string.scss', - '<%= dir.src %>/encode/types/_null.scss', - '<%= dir.src %>/encode/mixins/_json.scss', - '<%= dir.src %>/encode/api/_json.scss' - ], - dest: '<%= dir.dist %>/_<%= pkg.name %>.scss', - }, - }, + /** + * Scss Lint + * @see https://github.com/ahmednuaman/grunt-scss-lint + */ + scsslint: { + allFiles: [ + 'src/**/*.scss', + 'unit-testing/**/*.scss' + ], + options: { + config: '.scss-lint.yml', + colorizeOutput: false + }, + }, - // Sass - sass: { - options: { - style: 'expanded', - require : './lib/JsonImporter.rb', - loadPath: ['./node_modules/bootcamp/dist', './<%= dir.src %>'] - }, - all: { - files: { - './tmp/all.css': './test/test.scss' - } - }, - decoder: { - files: { - './tmp/decode.css': './test/decode/test.scss' - } - }, - encoder: { - files: { - './tmp/encode.css': './test/encode/test.scss' - } - } - }, + /** + * Mocha Cli + * @note used for Scss unit testing + * @see https://github.com/Rowno/grunt-mocha-cli + */ + mochacli: { + scss: ['unit-testing/tests.js'] + }, - scsslint : { - options : { - excludeLinter : [ - 'ColorKeyword', - 'NameFormat', - 'StringQuotes', - 'SpaceAfterComma', - 'Comment', - 'PropertySpelling' - ] - }, - all: { - src : ['<%= dir.src %>/**/*'] - }, - decoder: { - src : ['<%= dir.src %>/decoder/**/*'] - }, - encoder: { - src : ['<%= dir.src %>/encoder/**/*'] - } - }, + /** + * SassDoc + * @see https://github.com/SassDoc/grunt-sassdoc + */ + sassdoc: { + default: { + src: ['src/**/*.scss'], + options: { + dest: 'docs' + } + }, + }, - // Bootcamp - bootcamp: { - all: { - files: { - src: ['./tmp/all.css'] - } - }, - decoder:{ - files: { - src: ['./tmp/decode.css'] - } - }, - encoder:{ - files: { - src: ['./tmp/encode.css'] - } - } - }, - - // Watch - watch: { - all: { - files: [ - './test/**/*.scss', - './<%= dir.src %>/**/*.scss' - ], - tasks: ['test'] - }, - decoder: { - files: [ - './test/decode/**/*.scss', - './<%= dir.src %>/**/*.scss' + /** + * Watch + * @see https://github.com/gruntjs/grunt-contrib-watch + */ + watch: { + options: { + spawn: false, + }, + scss: { + files: ['src/**/*.scss'], + tasks: [ + 'scsslint', + 'mochacli:scss', + 'sassdoc', + 'notify:css' ], - tasks: ['test:decoder'] - }, - encoder: { - files: [ - './test/encode/**/*.scss', - './<%= dir.src %>/**/*.scss' - ], - tasks: ['test:encode'] - } - } - }); - - // Tasks - grunt.registerTask('test', function (arg){ - arg = arg || "all"; + }, + }, - var tasks = ['scsslint', 'sass', 'bootcamp'].map(function (item){ - return item + ":" + arg; - }); - - - grunt.task.run(tasks); - }); - grunt.registerTask('dev', function (arg ){ - arg = arg || "all"; + /** + * Notify + * @see https://github.com/dylang/grunt-notify + */ + notify: { + css: { + options: { + title: 'Success', + message: 'There were no errors running the compile tasks' + } + } + } - var tasks = ['test', 'watch'].map(function (item){ - return item + ":" + arg; }); + + /************************************************************** + * Load NPM Tasks + *************************************************************/ + + grunt.loadNpmTasks('grunt-contrib-clean') + grunt.loadNpmTasks('grunt-contrib-concat') + grunt.loadNpmTasks('grunt-contrib-watch'); + grunt.loadNpmTasks('grunt-mocha-cli'); + grunt.loadNpmTasks('grunt-notify'); + grunt.loadNpmTasks('grunt-sassdoc'); + grunt.loadNpmTasks('grunt-scss-lint'); + + /************************************************************** + * Tasks + *************************************************************/ + + // Default Grunt task + grunt.registerTask('default', [ + 'compile', + 'watch' + ]); + + // Compile the app + grunt.registerTask('compile', [ + 'scsslint', + 'mochacli', + 'clean', + 'concat', + 'sassdoc' + ]); - grunt.task.run(tasks); - }); - grunt.registerTask('build', ['test:all', 'concat']); -}; +}; \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 9977750..0000000 --- a/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Hugo Giraudel - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..7679684 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Edmund Reed + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index b9abfbd..8c8371b 100644 --- a/README.md +++ b/README.md @@ -1,116 +1,107 @@ -# SassyJSON [](http://badge.fury.io/js/sassyjson) [](http://badge.fury.io/rb/SassyJSON) [](https://travis-ci.org/HugoGiraudel/SassyJSON) +[](https://github.com/esr360/Sass-JSON/blob/master/LICENSE.txt) +[](https://travis-ci.org/esr360/Sass-JSON) +[](https://badge.fury.io/bo/Sass-JSON) +[](https://badge.fury.io/js/Sass-JSON) -SassyJSON is a Sass-powered API for JSON. It provides you the classic `json-encode` and `json-decode` directly from your Sass files. We'll leave you the only judges of the point of this. Read [API documentation](http://hugogiraudel.com/SassyJSON). +# Sass-JSON -## Install +> Output information about your Sass modules as JSON data -SassyJSON is available on [npm](https://npmjs.org/) or as a [Ruby Gem](http://rubygems.org/gems/SassyJSON). +[View Documentation (via SassDoc)](https://esr360.github.io/Sass-JSON/) -### Git +### Why? -``` git -git clone https://github.com/HugoGiraudel/SassyJSON.git && cd SassyJSON -``` +So you can access information about your Sass modules from your JavaScript. -### npm +### How? -``` bash -npm install sassyjson --save-dev -``` +All this library does is outputs a CSS selector with the `content` property populated with stringified JSON data converted from the Sass you pass to it, for example a Sass map. Once the data is in the stylesheet as JSON, it can be read from JavaScript using the [`Window.getComputedStyle()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle) method. -### Compass extension +### Requirements -1. `gem install SassyJSON` -2. Add `require 'SassyJSON'` to your `config.rb` -3. Import it in your stylesheets with `@import 'SassyJSON'` +* Sass 3.3+ -### Sass +### Installation -If you only want to play around the code without cloning the repo or using npm, you can find a [single file](https://github.com/HugoGiraudel/SassyJSON/blob/master/dist/_SassyJSON.scss) containing the whole API in the [dist](https://github.com/HugoGiraudel/SassyJSON/tree/master/dist) folder. +#### Via Bower -Also, SassyJSON is available at [Sassmeister](http://sassmeister.com/). +``` +bower install Sass-JSON +``` -## Example +#### Via NPM -### Encoding Sass to JSON +``` +npm install Sass-JSON +``` -#### Sass +#### As Git-Submodule -``` scss -$map: ((a: (1 2 ( b : 1 )), b: ( #444444, false, ( a: 1, b: test ) ), c: (2 3 4 string))); +> Ensure you change the PATH/TO/SUBMODULES part to your desired location -@include json-encode($map); +``` +git submodule add https://github.com/esr360/Sass-JSON.git PATH/TO/SUBMODULES ``` -#### CSS - -``` css -/*! json-encode: '{"a": [1, 2, {"b": 1}], "b": ["#444444", false, {"a": 1, "b": "test"}], "c": [2, 3, 4, "string"]}' */ - -body::before { - display:block; - width:0;height:0; - overflow:hidden; - content: '{"a": [1, 2, {"b": 1}], "b": ["#444444", false, {"a": 1, "b": "test"}], "c": [2, 3, 4, "string"]}'; -} +--- -head { - font-family: '{"a": [1, 2, {"b": 1}], "b": ["#444444", false, {"a": 1, "b": "test"}], "c": [2, 3, 4, "string"]}'; -} +After you have installed Sass-JSON, import the following file into your project's main .scss file: -@media -json-encode { - json { - json: '{"a": [1, 2, {"b": 1}], "b": ["#444444", false, {"a": 1, "b": "test"}], "c": [2, 3, 4, "string"]}'; - } -} +``` +src/_sass-json.scss ``` -If you want to restrict the output to only one of the three drivers (comment, media query or regular output) you can pass a flag as the second parameter with one of the four following keywords: `all`, `comment`, `media` or `regular`. Default is `all`. +To encode any Sass data to JSON, pass it through the `json-encode()` mixin: -### Decoding JSON to Sass +```scss +$your_data:( + 'foo' : 'alpha', + 'bar' : ( + 'baz' : 2, + 'qux' : #000000 + ) +); -``` scss -$json-decode: json-decode('{"a": [1, 2, {"b": 1}], "b": ["#444444", false, {"a": 1, "b": "test"}], "c": [2, 3, 4, "string"]}'); -// ("a": 1 2 ("b": 1), "b": #444444 false ("a": 1, "b": "test"), "c": 2 3 4 "string") +@include json-encode($value: $your_data, $selector: '#sassData'); ``` -## Importing and decoding a JSON file +As long as the element which matches your `$selector` value exists in the DOM, you will be able to access the data from your JavaScript: -To importe and decode an external `.json` file directly into a Sass variable: +```html +
-``` scss -@import 'SassyJSON'; // Import SassyJSON first! -@import 'relative/path/to/file.json?variable-name'; -// Do something with $variable-name + ``` -**Important:** +The above should log the following to your console: -* the path to the JSON file is relative to importing file -* the get parameter is the variable name to use it in Sass - -## Requirements +```js +{"foo": "alpha", "bar": {"baz": 2, "qux": "#000000"}} +``` -All you need is a clean version of Sass 3.3. Otherwise it's just pure Sass madness. +### Development -## Development +> The Sass unit test framework is [Sass True](https://github.com/oddbird/true) -### You need +#### Further Requirements - * [NodeJS](http://nodejs.org) - * [Ruby](https://www.ruby-lang.org/) - * Sass 3.3 via `gem install sass --pre` - * `grunt-cli` via `npm install -g grunt-cli` +* Node.js (+ npm) +* Grunt (`npm install -g grunt-cli`) +* Scss Lint (`gem install scss-lint`) -### How to +Install Node modules: - 1. Fork this repository - 2. Run `npm install` - 3. `grunt dev` - 4. Make your changes + write tests - 5. Commit + Pull request +``` +npm install +``` -## Credits +To run unit tests, generate documentation and lint the source files, run the following command: -* [Fabrice Weinberg](http://twitter.com/fweinb) -* [Hugo Giraudel](http://twitter.com/hugogiraudel) +``` +grunt compile +``` \ No newline at end of file diff --git a/SassyJSON.gemspec b/SassyJSON.gemspec deleted file mode 100644 index 7c2c55a..0000000 --- a/SassyJSON.gemspec +++ /dev/null @@ -1,38 +0,0 @@ -require './lib/SassyJSON' - -Gem::Specification.new do |s| - # Release Specific Information - s.version = SassyJSON::VERSION - s.date = SassyJSON::DATE - - # Gem Details - s.name = "SassyJSON" - s.rubyforge_project = "SassyJSON" - s.description = %q{Sass API for JSON} - s.summary = %q{SassyJSON is a Sass-powered API for JSON. It provides you the classic json-encode and json-decode directly from your Sass files.} - s.authors = ["Hugo Giraudel", "Fabrice Weinberg"] - s.email = ["hugo.giraudel@gmail.com", "fabrice@weinberg.me"] - s.homepage = "https://github.com/HugoGiraudel/SassyJSON/" - - # README file - s.files = ["README.md"] - - # CHANGELOG - s.files += ["CHANGELOG.md"] - - # Library Files - s.files += Dir.glob("lib/**/*.*") - - # Sass Files - s.files += Dir.glob("stylesheets/**/*.*") - - # Add to require - s.require_paths = ["lib", "stylesheets"] - - # Gem Bookkeeping - s.required_rubygems_version = ">= 1.3.6" - s.rubygems_version = %q{1.3.6} - - # Deps - #s.add_runtime_dependency 'sass', '>= 3.3.0' -end \ No newline at end of file diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..b6038ae --- /dev/null +++ b/bower.json @@ -0,0 +1,22 @@ +{ + "name": "Sass-JSON", + "version": "1.0.0", + "description": "Output information about your Sass modules as JSON data.", + "keywords": [ + "sass", + "scss", + "json", + "api" + ], + "authors": [ + "Hugo Giraudel", + "Edmund Reed (http://twitter.com/esr360)" + ], + "homepage": "https://github.com/esr360/Sass-JSON", + "main": "src/_sass-json.scss", + "license": "MIT", + "ignore": [ + "**/.*", + "node_modules" + ] +} \ No newline at end of file diff --git a/dist/_SassyJSON.scss b/dist/_SassyJSON.scss deleted file mode 100644 index 63addbc..0000000 --- a/dist/_SassyJSON.scss +++ /dev/null @@ -1,1075 +0,0 @@ -/*! sassyjson - v1.1.8 - 2014-06-01 */ -// Logs an error at `$pointer` with `$string` message -// -------------------------------------------------------------------------------- -// @param [string] $string: error message -// @param [number] $pointer: pointer position -// -------------------------------------------------------------------------------- -// @return [list] (pointer, false) - -@function _throw($string, $pointer) { - @warn "ERROR::#{$pointer}::#{$string}"; - @return $pointer, false; -} - -// Delay parsing to type-specific function -// according to found character -// -------------------------------------------------------------------------------- -// @param [string] $source: JSON complete source -// @param [number] $pointer: current pointer -// -------------------------------------------------------------------------------- -// @throw "Unexpected token $token." -// @throw "Empty JSON string." -// -------------------------------------------------------------------------------- -// @return [list|false] (new pointer, parsed value) - -@function _json-decode--value($source, $pointer) { - $length: str-length($source); - - @while $pointer <= $length { - $token: str-slice($source, $pointer, $pointer); - $pointer: $pointer + 1; - - @if $token == '{' { - @return _json-decode--map($source, $pointer); - } - @else if $token == '[' { - @return _json-decode--list($source, $pointer); - } - @else if $token == 't' { - @return _json-decode--true($source, $pointer); - } - @else if $token == 'f' { - @return _json-decode--false($source, $pointer); - } - @else if $token == '"' { - @return _json-decode--string($source, $pointer); - } - @else if $token == 'n' { - @return _json-decode--null($source, $pointer); - } - @else if index('1' '2' '3' '4' '5' '6' '7' '8' '9' '0' '-' '.', $token) { - @return _json-decode--number($source, $pointer); - } - @else if $token == ' ' or $token == " " { - // @continue; - } - @else { - @return _throw("Unexpected token `" + $token + "`.", $pointer); - } - } - - @return _throw("Empty JSON string.", $pointer); -} - -// Move pointer to position of token -// -------------------------------------------------------------------------------- -// @param [string] $source: JSON complete source -// @param [number] $pointer: current pointer -// @param [string] $token: token to reach -// -------------------------------------------------------------------------------- -// @throw "Expected $token; found {x}." -// @throw "Expected $token but reached end of stream." -// -------------------------------------------------------------------------------- -// @return [number|false] new pointer - -@function _consume($source, $pointer, $token) { - $length: str-length($source); - - @while $pointer <= $length { - $char: str-slice($source, $pointer, $pointer); - $pointer: $pointer + 1; - - @if $char == $token { - @return $pointer; - } - - @else if $char == " " or $char == " " { - // @continue; - } - - @else { - @return _throw("Expected `" + $token + "; ` found `" + $char + "`.", $pointer); - } - } - - @return _throw("Expected `" + $token + "` but reached end of stream.", $pointer); -} - -// Will find the first non escaped quote in a JSON String -// -------------------------------------------------------------------------------- -// @param [string] $string: to search in -// -------------------------------------------------------------------------------- -// @return [number] position of the first non escaped quote - -@function _find-ending-quote($string) { - $backslash: str-slice('\\', 1, 1); // Dirty hack to have a single backslash - $escaped-chars: '"\/bfnrtu'; // Characters that can be escaped in JSON - $hexadecimal-chars: '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '0' 'a' 'b' 'c' 'd' 'e' 'f'; - - $pos: 1; - $length: str-length($string); - $backslash-found: false; - - @while $pos <= $length { - $char: to-lower-case(str-slice($string, $pos, $pos)); - - // Previous char was a backslash - @if $backslash-found { - - // Special case, the 'u' character - @if $char == 'u' { - // Next 4 characters must be hexadecimal - @if not index($hexadecimal-chars, str-slice($string, $pos + 1, $pos + 1)) or - not index($hexadecimal-chars, str-slice($string, $pos + 2, $pos + 2)) or - not index($hexadecimal-chars, str-slice($string, $pos + 3, $pos + 3)) or - not index($hexadecimal-chars, str-slice($string, $pos + 4, $pos + 4)) { - @return 0; - } - - $pos: $pos + 4; - } - - // Invalid character escaped - @else if not str-index($escaped-chars, $char) { - @return 0; - } - - $backslash-found: false; - } - - @else if $char == $backslash { - $backslash-found: true; - } - - // Unescaped quote found - @else if $char == '"' { - @return $pos; - } - - $pos: $pos + 1; - } - - // No end of string found - @return 0; -} - -// Strip special carriage return characters -// -------------------------------------------------------------------------------- -// @param [string] $string: string to parse -// @param [string] $char: char to strip -// -------------------------------------------------------------------------------- -// @return [string] new string - -@function _strip-token($string, $token, $replace) { - - @while str-index($string, $token) and str-index($string, $token) > 0 { - $index: str-index($string, $token); - $string: str-slice($string, 1, $index - 1) + $replace + str-slice($string, $index + str-length($token)); - } - - @return $string; -} - -// Parses a JSON encoded string to see if it's a CSS length -// -------------------------------------------------------------------------------- -// @param [string] $string: JSON string -// -------------------------------------------------------------------------------- -// @return [number|string] string or number, depending on the match - -@function _length($string) { - @if type-of($string) == number { - @return $string; - } - - $strings: 'px' 'cm' 'mm' '%' 'ch' 'pica' 'in' 'em' 'rem' 'pt' 'pc' 'ex' 'vw' 'vh' 'vmin' 'vmax'; - $units: 1px 1cm 1mm 1% 1ch 1pica 1in 1em 1rem 1pt 1pc 1ex 1vw 1vh 1vmin 1vmax; - $number: ""; - $unit: ""; - - @for $i from 1 through str-length($string) { - $c: str-slice($string, $i, $i); - @if $c == ' ' or $c == " " { - @if $number != "" { - @return $string; - } - } - @else if index('0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '-' '.', $c) { - $number: $number + $c; - } - @else { - @if $number == "" { - @return $string; - } - $unit: $unit + $c; - } - } - - $number: nth(_json-decode--number($number, 2), 2); - $index: index($strings, to-lower-case($unit)); - - @if $index and $index > 0 { - @return $number * nth($units, $index); - } - - @return $string; -} - -// Parses a JSON encoded string to see if it's a CSS color -// -------------------------------------------------------------------------------- -// @param [string] $string: JSON string -// -------------------------------------------------------------------------------- -// @return [color|string] string or number, depending on the match - -@function _color($string) { - @if type-of($string) == color { - @return $string; - } - - $string-lower: to-lower-case($string); - $colors: transparent black silver gray white maroon red purple fuchsia green lime olive yellow navy blue teal aqua aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson cyan darkblue darkcyan darkgoldenrod darkgray darkgreen darkgrey darkkhaki darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray darkslategrey darkturquoise darkviolet deeppink deepskyblue dimgray dimgrey dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray green greenyellow grey honeydew hotpink indianred indigo ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan lightgoldenrodyellow lightgray lightgreen lightgrey lightpink lightsalmon lightseagreen lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime limegreen linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen mediumslateblue mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid palegoldenrod palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple red rosybrown royalblue saddlebrown salmon sandybrown seagreen seashell sienna silver skyblue slateblue slategray slategrey snow springgreen steelblue tan teal thistle tomato turquoise violet wheat white whitesmoke yellow yellowgreen; - $keywords: (); - - // Filling $keywords with stringified color keywords - @each $color in $colors { - $keywords: append($keywords, $color + ""); - } - - // Deal with inherit keyword - @if $string-lower == "inherit" { - @return unquote($string); - } - - // Deal with color keywords - @if index($keywords, $string-lower) { - @return nth($colors, index($keywords, $string-lower)); - } - - // Deal with hexadecimal triplets - @else if str-slice($string-lower, 1, 1) == '#' { - @return _from-hex($string); - } - - // Deal with rgb(a) colors - @else if str-slice($string-lower, 1, 3) == 'rgb' { - @return _from-rgb($string); - } - - // Deal with hsl(a) colors - @else if str-slice($string-lower, 1, 3) == 'hsl' { - @return _from-hsl($string); - } - - // Return string - @else { - @return $string; - } -} - -// Cast a stringified number / stringified percentage into number type -// -------------------------------------------------------------------------------- -// @param [string] $string: JSON string -// -------------------------------------------------------------------------------- -// @return [number] unitless number or percentage - -@function _get-color-value($string) { - $first: str-slice($string, 1, 1); - - // Pad <1 values with a leading 0 - @if $first == '.' { - $string: '0' + $string; - } - - $last: str-slice($string, -1, -1); - - @return if( - $last == '%', - nth(_json-decode--number(str-slice($string, 1, -2), 2), 2) * 1%, - nth(_json-decode--number($string, 2), 2) - ); -} - -// Cast a JSON encoded string into a hsl(a) color -// -------------------------------------------------------------------------------- -// @param [string] $string: JSON string -// -------------------------------------------------------------------------------- -// @return [color|string] string or hsl(a) color, depending on the match - -@function _from-hsl($string) { - $frags: (); - $string-lower: to-lower-case($string); - $is-alpha: str-slice($string-lower, 4, 4) == 'a'; - $length: str-length($string); - $start: str-index($string, "("); - - @for $i from $start through $length { - $token: str-slice($string-lower, $i, $i); - @if $token == ' ' or $token == " " { - // @continue; - } - @else if $token == '(' or $token == ',' { - $frags: append($frags, ""); - } - @else if $token == ')' { - @if length($frags) != if($is-alpha, 4, 3) { @return $string; } // Parsing error - $hue: _get-color-value(nth($frags, 1)); - $saturation: _get-color-value(nth($frags, 2)); - $lightness: _get-color-value(nth($frags, 3)); - - @if not $hue or not $saturation or not $lightness { - @return $string; - } - - @if $is-alpha { - @if length($frags) != 4 { @return $string; } // No alpha channel found - $alpha: _get-color-value(nth($frags, 4)); - @if not $alpha { @return $string; } // Error parsing alpha channel - @return hsla($hue, $saturation, $lightness, $alpha); - } - - @return hsl($hue, $saturation, $lightness); - } - @else { - $frags: set-nth($frags, length($frags), nth($frags, length($frags)) + $token); - } - } - - @return $string; -} - -// Cast a JSON encoded string into a rgb(a) color -// -------------------------------------------------------------------------------- -// @param [string] $string: JSON string -// -------------------------------------------------------------------------------- -// @return [color|string] string or rgb(a) color depending on the match - -@function _from-rgb($string) { - $string-lower: to-lower-case($string); - $frags: (); - $is-alpha: str-slice($string-lower, 4, 4) == 'a'; - $start: str-index($string, "("); - $length: str-length($string); - - @for $i from $start through $length { - $token: str-slice($string-lower, $i, $i); - @if $token == ' ' or $token == " " { - // @continue; - } - @else if $token == '(' or $token == ',' { - $frags: append($frags, ""); - } - @else if $token == ')' { - @if length($frags) != if($is-alpha, 4, 3) { @return $string; } // Parsing error - $red: _get-color-value(nth($frags, 1)); - $green: _get-color-value(nth($frags, 2)); - $blue: _get-color-value(nth($frags, 3)); - - @if not $red or not $green or not $blue { - @return $string; - } - - @if $is-alpha { - @if length($frags) != 4 { @return $string; } // No alpha channel found - $alpha: _get-color-value(nth($frags, 4)); - @if not $alpha { @return $string; } // Error parsing alpha channel - @return rgba($red, $green, $blue, $alpha); - } - - @return rgb($red, $green, $blue); - } - @else { - $frags: set-nth($frags, length($frags), nth($frags, length($frags)) + $token); - } - } - - @return $string; -} - -// Cast a JSON encoded string into a hexadecimal color -// -------------------------------------------------------------------------------- -// @param [string] $string: JSON string -// -------------------------------------------------------------------------------- -// @return [color|string] string or hex color depending on the match - -@function _from-hex($string) { - $string-lower: to-lower-case($string); - $r: ""; $g: ""; $b: ""; - $hex: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "a" "b" "c" "d" "e" "f"; - $length: str-length($string); - $max: if($length == 4, 1, 2); - - // Check for length accuracy - @if $length != 4 and $length != 7 { - @return $string; - } - - // Loop from the second character (omitting #) - @for $i from 2 through $length { - $c: str-slice($string-lower, $i, $i); - - // If wrong character, return - @if not index($hex, $c) { - @return $string; - } - - @if str-length($r) < $max { $r: $r + $c } - @else if str-length($g) < $max { $g: $g + $c } - @else if str-length($b) < $max { $b: $b + $c } - } - - @if $length == 4 { - $r: $r + $r; - $g: $g + $g; - $b: $b + $b; - } - - @return rgb(_hex-to-dec($r), _hex-to-dec($g), _hex-to-dec($b)); -} - -// Convert an hexadecimal number to a decimal number -// -------------------------------------------------------------------------------- -// @param [string] $string: hexadecimal value -// -------------------------------------------------------------------------------- -// @return [number] decimal number - -@function _hex-to-dec($string) { - $hex: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "a" "b" "c" "d" "e" "f"; - $string: to-lower-case($string); - $length: str-length($string); - - $dec: 0; - @for $i from 1 through $length { - $factor: 1 + (15 * ($length - $i)); - $index: index($hex, str-slice($string, $i, $i)); - $dec: $dec + $factor * ($index - 1); - } - - @return $dec; -} - -// Power function -// -------------------------------------------------------------------------------- -// @param [number] $x: number -// @param [number] $n: power -// -------------------------------------------------------------------------------- -// @return [number] $x ^ $n - -@function _pow($x, $n) { - @if $n == 0 { @return 1; } - $ret: 1; - @if $n >= 0 { - @for $i from 1 through $n { - $ret: $ret * $x; - } - } @else { - @for $i from $n to 0 { - $ret: $ret / $x; - } - } - - @return $ret; -} - -// Parses a JSON encoded number to find the integer part -// -------------------------------------------------------------------------------- -// @param [string] $source: JSON complete source -// @param [number] $pointer: current pointer -// -------------------------------------------------------------------------------- -// @throw "Unexpected token $token." -// -------------------------------------------------------------------------------- -// @return [list|false] (new pointer, parsed number) - -@function _find-integer($source, $pointer) { - $source: to-lower-case($source); - $length: str-length($source); - $numbers: '0' '1' '2' '3' '4' '5' '6' '7' '8' '9'; - $result: 0; - - @while $pointer <= $length { - $token: str-slice($source, $pointer, $pointer); - $index: index($numbers, $token); - - @if $token == '-' { - // do nothing - } - @else if $index { - $result: $result * 10 + ($index - 1); - } - @else { - @if index('e' '.' ' ' ',' ']' '}', $token) { - @return $pointer, $result; - } - @return _throw("Unexpected token `" + $token + "`.", $pointer); - } - - $pointer: $pointer + 1; - } - - @return $pointer, $result; -} - -// Parses a JSON encoded number to find the digits -// -------------------------------------------------------------------------------- -// @param [string] $source: JSON complete source -// @param [number] $pointer: current pointer -// -------------------------------------------------------------------------------- -// @throw "Unexpected token $token." -// -------------------------------------------------------------------------------- -// @return [list|false] (new pointer, parsed number) - -@function _find-digits($source, $pointer) { - $source: to-lower-case($source); - $length: str-length($source); - $numbers: '0' '1' '2' '3' '4' '5' '6' '7' '8' '9'; - $result: null; - $runs: 1; - - @while $pointer <= $length { - $token: str-slice($source, $pointer, $pointer); - $index: index($numbers, $token); - - @if $token == '.' { - // @continue; - } - @else if $index and $index > 0 { - $runs: $runs * 10; - $result: if($result == null, ($index - 1), $result * 10 + ($index - 1)); - } - @else { - @if index('e' '.' ' ' ',' ']' '}', $token) { - @return $pointer, if($result != null, $result / $runs, $result); - } - @return _throw("Unexpected token `" + $token + "`.", $pointer); - } - - $pointer: $pointer + 1; - } - - @return $pointer, if($result != null, $result / $runs, $result); -} - -// Parses a JSON encoded number to find the exponent part -// -------------------------------------------------------------------------------- -// @param [string] $source: JSON complete source -// @param [number] $pointer: current pointer -// -------------------------------------------------------------------------------- -// @throw "Unexpected token $token." -// -------------------------------------------------------------------------------- -// @return [list|false] (new pointer, parsed number) - -@function _find-exponent($source, $pointer) { - $source: to-lower-case($source); - $length: str-length($source); - $numbers: '0' '1' '2' '3' '4' '5' '6' '7' '8' '9'; - $result: null; - $minus: null; - - @while $pointer <= $length { - $token: str-slice($source, $pointer, $pointer); - $index: index($numbers, $token); - - @if $token == 'e' { - // @continue; - } - @else if $token == '-' { - @if $minus != null { - @return _throw("Unexpected token `-`.", $pointer); - } - $minus: true; - } - @else if $token == '+' { - @if $minus != null { - @return _throw("Unexpected token `+`.", $pointer); - } - $minus: false; - } - @else if $index and $index > 0 { - $result: if($result == null, ($index - 1), $result * 10 + ($index - 1)); - } - @else { - @if not index(' ' ',' ']' '}', $token) { - @return _throw("Unexpected token `" + $token + "`.", $pointer); - } - - @return $pointer, if($minus and $result != null, $result * -1, $result); - } - - $pointer: $pointer + 1; - } - - @return $pointer, if($minus and $result != null, $result * -1, $result); -} - -// Parses a JSON encoded string -// -------------------------------------------------------------------------------- -// @param [string] $source: JSON complete source -// @param [number] $pointer: current pointer -// -------------------------------------------------------------------------------- -// @throw "Unterminated string." -// -------------------------------------------------------------------------------- -// @return [list|false] (new pointer, parsed string / color / length) - -@function _json-decode--string($source, $pointer) { - // Check for the end of the string - $temp: str-slice($source, $pointer); - $end: _find-ending-quote($temp); - $string: ""; - - // If no end is found - @if not $end or $end == 0 { - @return _throw("Unterminated string.", $pointer); - } - - // If string is not empty - @else if $end > 1 { - $string: str-slice($temp, 1, $end - 1); - - $cr: " - "; - $string: _strip-token($string, "\r", $cr); - $string: _strip-token($string, "\n", $cr); - $string: _strip-token($string, '\\\"', '"'); - - // Test whether the string could be a CSS length - $string: _length($string); - - // Test whether the string could be a CSS color - @if type-of($string) == string { - $string: _color($string); - } - } - - @return ($pointer + $end, $string); -} - -// Parses a JSON encoded `true` -// -------------------------------------------------------------------------------- -// @param [string] $source: JSON complete source -// @param [number] $pointer: current pointer -// -------------------------------------------------------------------------------- -// @throw "Unexpected token `t`." -// -------------------------------------------------------------------------------- -// @return [list|false] (new pointer, true) - -@function _json-decode--true($source, $pointer) { - $length: str-length($source); - @if $length - $pointer < 2 - or str-slice($source, $pointer, $pointer) != 'r' - or str-slice($source, $pointer + 1, $pointer + 1) != 'u' - or str-slice($source, $pointer + 2, $pointer + 2) != 'e' { - @return _throw("Unexpected token: `t`.", $pointer); - } - @return ($pointer + 3, true); -} - -// Parses a JSON encoded `false` -// -------------------------------------------------------------------------------- -// @param $source: JSON complete source -// @param $pointer: current pointer -// -------------------------------------------------------------------------------- -// @throw "Unexpected token `f`." -// -------------------------------------------------------------------------------- -// @return [list|false] (new pointer, false) - -@function _json-decode--false($source, $pointer) { - $length: str-length($source); - @if $length - $pointer < 3 - or str-slice($source, $pointer, $pointer) != 'a' - or str-slice($source, $pointer + 1, $pointer + 1) != 'l' - or str-slice($source, $pointer + 2, $pointer + 2) != 's' - or str-slice($source, $pointer + 3, $pointer + 3) != 'e' { - @return _throw("Unexpected token: `f`.", $pointer); - } - @return ($pointer + 4, false); -} - -// Parses a JSON encoded `null` -// -------------------------------------------------------------------------------- -// @param [string] $source: JSON complete source -// @param [number] $pointer: current pointer -// -------------------------------------------------------------------------------- -// @throw "Unexpected token `n`." -// -------------------------------------------------------------------------------- -// @return [list|false] (new pointer, null) - -@function _json-decode--null($source, $pointer) { - $length: str-length($source); - @if $length - $pointer < 2 - or str-slice($source, $pointer, $pointer) != 'u' - or str-slice($source, $pointer + 1, $pointer + 1) != 'l' - or str-slice($source, $pointer + 2, $pointer + 2) != 'l' { - @return _throw("Unexpected token: `n`.", $pointer); - } - @return ($pointer + 3, null); -} - -// Parses a JSON encoded number -// -------------------------------------------------------------------------------- -// @param [string] $source: JSON complete source -// @param [number] $pointer: current pointer -// -------------------------------------------------------------------------------- -// @throw "Unexpected token $token." -// @throw "Unexpected end of stream." -// -------------------------------------------------------------------------------- -// @return [list|false] (new pointer, parsed number) - -@function _json-decode--number($source, $pointer) { - $pointer: $pointer - 1; // Move back pointer to begininng of number - $allowed: '-' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9'; // Allowed characted to start with - $first: str-slice($source, $pointer, $pointer); // First character of the number - $minus: $first == '-'; // Is it negative? - - // Early check for errors - @if not index($allowed, $first) { - @return _throw("Unexpected token `" + $first + "`.", $pointer); - } - - // Find the integer part - $find-integer: _find-integer($source, $pointer); - $pointer: nth($find-integer, 1); - $result: nth($find-integer, 2); - @if not $result { // Error occured - @return $find-integer; - } - - // Find digits - @if str-slice($source, $pointer, $pointer) == '.' { - $find-digits: _find-digits($source, $pointer); - $pointer: nth($find-digits, 1); - $digits: nth($find-digits, 2); - - @if $digits == null { // Empty digits, throw error - @return _throw("Unexpected end of stream.", $pointer); - } - @else if $digits == false { // Error occured, return it - @return $find-digits; - } - - $result: $result + $digits; - } - - // Find exponent - @if to-lower-case(str-slice($source, $pointer, $pointer)) == 'e' { - $find-exponent: _find-exponent($source, $pointer); - $pointer: nth($find-exponent, 1); - $exponent: nth($find-exponent, 2); - - @if $exponent == null { // Empty exponent, throw error - @return _throw("Unexpected end of stream.", $pointer); - } - @else if $exponent == false { // Error occured, return it - @return $find-exponent; - } - - $result: $result * _pow(10, $exponent); - } - - @return ($pointer, if($minus, $result * -1, $result)); -} - -// Parses a JSON encoded array -// -------------------------------------------------------------------------------- -// @param [string] $source: JSON complete source -// @param [number] $pointer: current pointer -// -------------------------------------------------------------------------------- -// @throw "Unexpected comma in array literal." -// @throw "Missing comma in array literal." -// @throw "Unterminated array literal." -// -------------------------------------------------------------------------------- -// @return [list|false] (new pointer, parsed list) - -@function _json-decode--list($source, $pointer) { - $length: str-length($source); - $list: (); - $needs-comma: false; - - @if $pointer <= $length and str-slice($source, $pointer, $pointer) == "]" { - @return ($pointer + 1, $list); - } - - @while $pointer <= $length { - $token: str-slice($source, $pointer, $pointer); - - @if $token == "]" { - @if not $needs-comma and length($list) != 0 { - @return _throw("Unexpected comma in array literal.", $pointer); - } - - // Do it the Sass way and destruct a single item array to an element. - @return ($pointer + 1, if(length($list) == 1, nth($list, 1), $list)); - } - @else if $token == " " or $token == " " { - $pointer: $pointer + 1; - } - @else if $token == "," { - @if not $needs-comma { - @return _throw("Unexpected comma in array literal.", $pointer); - } - $needs-comma: false; - $pointer: $pointer + 1; - } - @else { - @if $needs-comma { - @return _throw("Missing comma in array literal.", $pointer); - } - $read: _json-decode--value($source, $pointer); - $pointer: nth($read, 1); - $list: append($list, nth($read, 2)); - $needs-comma: true; - } - } - - @return _throw("Unterminated array literal.", $pointer); -} - -// Parses a JSON encoded object -// -------------------------------------------------------------------------------- -// @param [string] $source: JSON complete source -// @param [number] $pointer: current pointer -// -------------------------------------------------------------------------------- -// @throw "Unexpected comma in object literal." -// @throw "Unexpected token $token in object literal." -// @throw "Missing comma in object literal." -// @throw "Unterminated object literal." -// @throw "Consuming token `:` failed." -// -------------------------------------------------------------------------------- -// @return [list|false] (new pointer, map) - -@function _json-decode--map($source, $pointer) { - $length: str-length($source); - $map: (); - $needs-comma: false; - - // Deal with empty map - @if $pointer <= $length and str-slice($source, $pointer, $pointer) == "}" { - @return ($pointer + 1, $map); - } - - @while $pointer <= $length { - $token: str-slice($source, $pointer, $pointer); - $pointer: $pointer + 1; - - @if $token == "}" { - @if not $needs-comma and length($map) != 0 { - @return _throw("Unexpected comma in object literal.", $pointer); - } - @return ($pointer, $map); - } - - @else if $token == " " or $token == " " { - // @continue; - } - - @else if $token == "," { - @if not $needs-comma { - @return _throw("Unexpected comma in object literal.", $pointer); - } - $needs-comma: false; - } - - @else if $token == '"' { - @if $needs-comma { - @return _throw("Missing comma in object literal.", $pointer); - } - - // Read key - $read-key: _json-decode--string($source, $pointer); - $pointer: nth($read-key, 1); - $key: nth($read-key, 2); - - // Remove colon - $pointer: _consume($source, $pointer, ":"); - @if length($pointer) > 1 { // If consume has failed - @return _throw("Consuming token `:` failed.", 0); - } - - // Read value - $read-value: _json-decode--value($source, $pointer); - $pointer: nth($read-value, 1); - $value: nth($read-value, 2); - - // Add pair to map - $map: map-merge($map, ($key: $value)); - $needs-comma: true; - } - - @else { - @return _throw("Unexpected token `" + $token + "` in object literal.", $pointer); - } - } - - @return _throw("Unterminated object literal.", $pointer); -} - -// Parse a JSON string -// -------------------------------------------------------------------------------- -// @param $json: JSON string to parse -// -------------------------------------------------------------------------------- -// @throw "Input string may not be null" -// -------------------------------------------------------------------------------- -// @return [literal|false] - -@function json-decode($json) { - $length: str-length($json); - $pointer: 1; - $value: null; - - @if $json == null { - @return _throw("Input string may not be null.", $pointer); - } - - @while $value != false // Stop if error - and $pointer <= $length { - $read: _json-decode--value($json, $pointer); - $pointer: nth($read, 1); - $value: nth($read, 2); - } - - @return $value; -} - -// Proof quote a value -// -------------------------------------------------------------------------------- -// @param $value: value to be quoted -// -------------------------------------------------------------------------------- -// @return [string] quoted value - -@function _proof-quote($value) { - @return '"' + $value + '"'; -} - -// Encode a bool to JSON -// -------------------------------------------------------------------------------- -// @param $bool: bool to be encoded -// -------------------------------------------------------------------------------- -// @return [bool] boolean - -@function _json-encode--bool($boolean) { - @return $boolean; -} - -// Encode a color to JSON -// -------------------------------------------------------------------------------- -// @param $color: color to be encoded -// -------------------------------------------------------------------------------- -// @return [string] encoded color - -@function _json-encode--color($color) { - @return _proof-quote($color); -} - -// Encode a list to JSON -// -------------------------------------------------------------------------------- -// @param $list: list to be encoded -// -------------------------------------------------------------------------------- -// @return [string] encoded list - -@function _json-encode--list($list) { - $str: ""; - @each $item in $list { - $str: $str + ', ' + json-encode($item); - } - @return '[' + str-slice($str, 3) + ']'; -} - -// Encode a map to JSON -// -------------------------------------------------------------------------------- -// @param $map: map to be encoded -// -------------------------------------------------------------------------------- -// @return [string] encoded map - -@function _json-encode--map($map) { - $str: ""; - @each $key, $value in $map { - $str: $str + ', ' + _proof-quote($key) + ': ' + json-encode($value); - } - @return '{' + str-slice($str, 3) + '}'; -} - -// Encode a number to JSON -// -------------------------------------------------------------------------------- -// @param $number: number to be encoded -// -------------------------------------------------------------------------------- -// @return [string] encoded number - -@function _json-encode--number($number) { - @return if(unitless($number), $number, _proof-quote($number)); -} - -// Encode a string to JSON -// -------------------------------------------------------------------------------- -// @param $string: string to be encoded -// -------------------------------------------------------------------------------- -// @return [string] encoded string - -@function _json-encode--string($string) { - @return _proof-quote($string); -} - -// Encode `null` to JSON -// -------------------------------------------------------------------------------- -// @param $null: `null` -// -------------------------------------------------------------------------------- -// @return [string] `null` - -@function _json-encode--null($null) { - @return "null"; -} - -// JSON.stringify a value and pass it as a font-family of head element -// -------------------------------------------------------------------------------- -// @param $value: value to be stringified -// @parem $flag: output driver - -@mixin json-encode($value, $flag: all) { - $flag: if(not index(all regular media comment, $flag), all, $flag); - $json: json-encode($value); - - // Persistent comment - @if $flag == comment or $flag == all { - /*! json-encode: #{$json} */ - } - // Regular property value pair - @if $flag == regular or $flag == all { - // All browsers except IE8- - body::before { - // This element must be in the render tree to get it via getComputedStyle(document.body, ':before'); - content: json-encode($value); - display: block; - height: 0; - overflow: hidden; - width: 0; - } - - // All browsers except Opera (Presto based) - head { - font-family: json-encode($value); - } - } - - // Falsy media query - @if $flag == media or $flag == all { - @media -json-encode { - json { - json: $json; - } - } - } -} - -// Delay the encoding of ta literal to JSON -// to a type-specific method -// -------------------------------------------------------------------------------- -// @param $value: value to be stringified -// -------------------------------------------------------------------------------- -// @throw "Unknown type for $value ( {x} )." -// -------------------------------------------------------------------------------- -// @return [string|false] JSON encoded string - -@function json-encode($value) { - $type: type-of($value); - @if function_exists('_json-encode--#{$type}') { - @return call('_json-encode--#{$type}', $value); - } - @warn "Unknown type for #{$value} (#{$type})."; - @return false; -} diff --git a/dist/_sass-json.scss b/dist/_sass-json.scss new file mode 100644 index 0000000..407d783 --- /dev/null +++ b/dist/_sass-json.scss @@ -0,0 +1,182 @@ +/// Delay the encoding of a literal to JSON to a type-specific method +/// +/// @author Hugo Giraudel +/// @access public +/// +/// @require {function} _json-encode--string +/// @require {function} _json-encode--number +/// @require {function} _json-encode--list +/// @require {function} _json-encode--map +/// @require {function} _json-encode--null +/// @require {function} _json-encode--color +/// @require {function} _json-encode--bool +/// +/// @param {*} $value - value to be stringified +/// +/// @throw Unknown type for #{$value} (#{$type}). +/// @return {string} - JSON encoded string +@function json-encode($value) { + $type: type-of($value); + + @if function-exists('_json-encode--#{$type}') { + @return call('_json-encode--#{$type}', $value); + } + + @error 'Unknown type for #{$value} (#{$type}).'; +} +/// Proof quote a value +/// +/// @author Hugo Giraudel +/// @access public +/// +/// @param {*} $value - value to be quoted +/// +/// @return {string} - quoted value +@function _proof-quote($value) { + $value: to-string($value); + @return '"' + $value + '"'; +} +/// Joins all elements of `$list` with `$glue` +/// +/// @author Hugo Giraudel +/// @access public +/// +/// @param {List} $list - list to cast +/// @param {String} $glue ('') - value to use as a join string +/// +/// @return {String} - quoted value +@function to-string($list, $glue: '', $is-nested: false, $recursive: false) { + $result: ''; + + @for $i from 1 through length($list) { + $e: nth($list, $i); + @if type-of($e) == 'list' and $recursive { + $result: $result + to-string($e, $glue, $is-nested: true, $recursive: true); + } @else { + $result: if( + $i != length($list) or $is-nested, + $result + $e + $glue, $result + $e + ); + } + } + + @return $result; +} +/// JSON.stringify a value and pass it to the content property of a specified selector +/// +/// @author Hugo Giraudel +/// @access public +/// +/// @require {function} json-encode +/// +/// @param {*} $value - value to be stringified +/// @param {string} $selector ['#modulesConfigJSON'] - DOM selector to hold config +@mixin json-encode($value, $selector: '#modulesConfigJSON') { + #{$selector}::before { + content: json-encode($value); + display: block; + height: 0; + overflow: hidden; + width: 0; + } +} +/// Encode a bool to JSON +/// +/// @author Hugo Giraudel +/// @access private +/// +/// @param {bool} $bool - bool to be encoded +/// +/// @return {bool} - encoded bool +@function _json-encode--bool($boolean) { + @return $boolean; +} +/// Encode a color to JSON +/// +/// @author Hugo Giraudel +/// @access private +/// +/// @require {function} _proof-quote +/// +/// @param {color} $color - color to be encoded +/// +/// @return {string} - encoded color +@function _json-encode--color($color) { + @return _proof-quote($color); +} +/// Encode a list to JSON +/// +/// @author Hugo Giraudel +/// @access private +/// +/// @require {function} json-encore +/// +/// @param {list} $list - list to be encoded +/// +/// @return {string} - encoded list +@function _json-encode--list($list) { + $str: ''; + + @each $item in $list { + $str: $str + ', ' + json-encode($item); + } + + @return '[' + str-slice($str, 3) + ']'; +} +/// Encode a map to JSON +/// +/// @author Hugo Giraudel +/// @access private +/// +/// @require {function} _proof-quote +/// @require {function} json-encode +/// +/// @param {map} $map - map to be encoded +/// +/// @return {string} - encoded map +@function _json-encode--map($map) { + $str: ''; + + @each $key, $value in $map { + $str: $str + ', ' + _proof-quote($key) + ': ' + json-encode($value); + } + + @return '{' + str-slice($str, 3) + '}'; +} +/// Encode `null` to JSON +/// +/// @author Hugo Giraudel +/// @access private +/// +/// @param {null} $null - `null` +/// +/// @return {string} +@function _json-encode--null($null) { + @return 'null'; +} +/// Encode a number to JSON +/// +/// @author Hugo Giraudel +/// @access private +/// +/// @require {function} _proof-quote +/// +/// @param {number} $number - number to be encoded +/// +/// @return {string} - encoded number +@function _json-encode--number($number) { + @return if(unitless($number), $number, _proof-quote($number)); +} +/// Encode a string to JSON +/// +/// @author Hugo Giraudel +/// @access private +/// +/// @require {function} _proof-quote +/// +/// @param {string} $string - string to be encoded +/// +/// @return {string} - encoded string +@function _json-encode--string($string) { + @return _proof-quote($string); +} \ No newline at end of file diff --git a/docs/assets/css/main.css b/docs/assets/css/main.css new file mode 100644 index 0000000..c30e6a0 --- /dev/null +++ b/docs/assets/css/main.css @@ -0,0 +1 @@ +.container:after,.header:after,.searchbar:after{content:"";display:table;clear:both}.visually-hidden{width:1px;height:1px;position:absolute;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);border:0}.sidebar__title{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}code[class*='language-'],pre[class*='language-']{color:black;text-shadow:0 1px white;font-family:Consolas, Monaco, 'Andale Mono', monospace;direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*='language-']::-moz-selection,pre[class*='language-'] ::-moz-selection,code[class*='language-']::-moz-selection,code[class*='language-'] ::-moz-selection{text-shadow:none;background:#b3d4fc}pre[class*='language-']::selection,pre[class*='language-'] ::selection,code[class*='language-']::selection,code[class*='language-'] ::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*='language-'],pre[class*='language-']{text-shadow:none}}pre[class*='language-']{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*='language-'],pre[class*='language-']{background:white}:not(pre)>code[class*='language-']{padding:.1em;border-radius:.3em}.token.comment,.token.prolog,.token.doctype,.token.cdata{color:slategray}.token.punctuation{color:#999}.namespace{opacity:.7}.token.property,.token.tag,.token.boolean,.token.number,.token.constant,.token.symbol{color:#905}.token.selector,.token.attr-name,.token.string,.token.builtin{color:#690}.token.operator,.token.entity,.token.url,.language-css .token.string,.style .token.string,.token.variable{color:#a67f59;background:rgba(255,255,255,0.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.regex,.token.important{color:#e90}.token.important{font-weight:bold}.token.entity{cursor:help}html{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*,*::after,*::before{-webkit-box-sizing:inherit;-moz-box-sizing:inherit;box-sizing:inherit}body{font:1em/1.35 "Open Sans","Helvetica Neue Light","Helvetica Neue","Helvetica","Arial",sans-serif;overflow:auto;margin:0}a{transition:0.15s;text-decoration:none;color:#dd5a6f}a:hover,a:hover code{color:#333}table p{margin:0 0 0.5rem}:not(pre)>code{color:#dd5a6f;white-space:nowrap;font-weight:normal}@media (max-width: 800px){table,tbody,tr,td,th{display:block}thead{width:1px;height:1px;position:absolute;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);border:0}tr{padding-bottom:1em;margin-bottom:1em;border-bottom:2px solid #ddd}td::before,th::before{content:attr(data-label) ": ";text-transform:capitalize;font-weight:bold}td p,th p{display:inline}}.layout-toggle{display:none}@media (min-width: 801px){.layout-toggle{position:absolute;top:8px;left:20px;font-size:2em;cursor:pointer;color:white;display:block}}@media (min-width: 801px){.sidebar-closed .sidebar{-webkit-transform:translateX(-280px);-ms-transform:translateX(-280px);transform:translateX(-280px)}.sidebar-closed .main{padding-left:0}.sidebar-closed .header{left:0}}.list-unstyled{padding-left:0;list-style:none;line-height:1.5;margin-top:0;margin-bottom:1.5rem}.list-inline li{display:inline-block}.container{max-width:100%;width:1170px;margin:0 auto;padding:0 2rem}.relative{position:relative}.clear{clear:both}.header{position:fixed;top:0;right:0;left:280px;box-shadow:0 2px 5px rgba(0,0,0,0.26);padding:1em 0;background:#dd5a6f;color:#e0e0e0;z-index:4000}@media (max-width: 800px){.header{left:0}}@media (min-width: 801px){.header{transition:0.2s cubic-bezier(0.215, 0.61, 0.355, 1)}}.header__title{font-weight:500;text-align:center;margin:0 0 0.5em 0}.header__title a{color:#e0e0e0}@media (min-width: 801px){.header__title{float:left;font-size:1em;margin-top:.25em;margin-bottom:0}}.searchbar{display:inline-block;float:right}@media (max-width: 800px){.searchbar{display:block;float:none}}.searchbar__form{float:right;position:relative}@media (max-width: 800px){.searchbar__form{float:none}}@media (min-width: 801px){.searchbar__form{min-width:15em}}.searchbar__field{border:none;padding:0.5em;font-size:1em;margin:0;width:100%;box-shadow:0 1.5px 4px rgba(0,0,0,0.24),0 1.5px 6px rgba(0,0,0,0.12);border:1px solid #e0e0e0}.searchbar__suggestions{position:absolute;top:100%;right:0;left:0;box-shadow:0 1.5px 4px rgba(0,0,0,0.24),0 1.5px 6px rgba(0,0,0,0.12);border:1px solid #e0e0e0;background:white;padding:0;margin:0;list-style:none;z-index:2}.searchbar__suggestions:empty{display:none}.searchbar__suggestions .selected{background:#ddd}.searchbar__suggestions li{border-bottom:1px solid #e0e0e0}.searchbar__suggestions li:last-of-type{border:none}.searchbar__suggestions a{display:block;padding:0.5em;font-size:0.9em}.searchbar__suggestions a:hover,.searchbar__suggestions a:active,.searchbar__suggestions a:focus{background:#e0e0e0}.searchbar__suggestions code{margin-right:.5em}@media (min-width: 801px){.sidebar{position:fixed;top:0;bottom:0;left:0;overflow:auto;box-shadow:1px 0 1.5px rgba(0,0,0,0.12);width:280px;z-index:2;border-right:1px solid #e0e0e0;transition:0.2s cubic-bezier(0.215, 0.61, 0.355, 1)}}@media (max-width: 800px){.sidebar{margin-top:4em}}.sidebar__annotation{color:#5c4863}.sidebar__item{font-size:0.9em}.sidebar__item a{padding:0.5em 4.5em;display:block;text-decoration:none;color:#333}.sidebar__item:hover,.sidebar__item:active,.sidebar__item:focus{background:#e0e0e0}.sidebar__item.is-collapsed+*{display:none}.sidebar__item--heading{padding:1em 1.5em}.sidebar__item--heading a{font-weight:bold}.sidebar__item--sub-heading{padding:0.5em 2.5em}.sidebar__item--sub-heading a{color:#888}.sidebar__item--heading,.sidebar__item--sub-heading{position:relative}.sidebar__item--heading:after,.sidebar__item--sub-heading:after{position:absolute;top:50%;right:2em;content:'\25BC';margin-top:-0.5em;color:#ddd;font-size:0.7em}.sidebar__item--heading.is-collapsed:after,.sidebar__item--sub-heading.is-collapsed:after{content:'\25B6'}.sidebar__item--heading a,.sidebar__item--sub-heading a{padding:0;display:inline}.sidebar__description{color:#e0e0e0;padding-right:2em}.sidebar__header{border-bottom:1px solid #e0e0e0}.sidebar__title{font-size:1em;margin:0;padding:1.45em}.btn-toggle{background:#EFEFEF;border:none;border-bottom:1px solid #e0e0e0;display:block;padding:1em;width:100%;cursor:pointer;color:#999;font-weight:bold;margin:0;transition:0.15s ease-out}.btn-toggle:hover,.btn-toggle:active,.btn-toggle:focus{background:#DFDFDF}.main{background:#f9f9f9;position:relative}@media (min-width: 801px){.main{transition:0.2s cubic-bezier(0.215, 0.61, 0.355, 1);padding-left:280px;padding-top:4em;min-height:45em}}.main__section{margin-top:5em;border-top:5px solid rgba(92,72,99,0.2)}.header+.main__section{margin-top:0;border-top:none}.main__heading,.main__heading--secondary{padding:1em 0;margin-top:0}@media (min-width: 801px){.main__heading,.main__heading--secondary{padding:2em 0 0}}.main__heading{color:#5c4863;font-size:3.5em;text-align:center;border-bottom:5px solid rgba(92,72,99,0.2);padding-bottom:.5em;margin-bottom:1em;background:rgba(92,72,99,0.1)}.main__heading--secondary{font-size:3em;color:#dd5a6f;text-transform:uppercase;font-weight:bold;padding-top:0;margin-bottom:-3rem;position:relative}.main__heading--secondary .container{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.main__heading--secondary::before{content:'';position:absolute;left:0;right:0;bottom:0.15em;height:0.2em;background-color:#dd5a6f}.footer{background:#e0e0e0;padding:1em 0}.footer .container{position:relative}.footer__project-info{float:left}.footer__watermark{position:absolute;right:0;top:-0.7em}.footer__watermark img{display:block;max-width:7em}.project-info__name,.project-info__version,.project-info__license{display:inline-block}.project-info__version,.project-info__license{color:#555}.project-info__license{text-indent:-0.25em}.main__section{margin-bottom:4.5rem}.item__heading{color:#333;margin:4.5rem 0 1.5rem 0;position:relative;font-size:2em;font-weight:300;float:left}.item__name{color:#dd5a6f}.item__example{margin-bottom:1.5rem}.item__example,.item__code{box-shadow:0 1.5px 4px rgba(0,0,0,0.24),0 1.5px 6px rgba(0,0,0,0.12);border:1px solid #e0e0e0;word-wrap:break-word;line-height:1.42}.item__code{padding-right:7em;clear:both;cursor:pointer}.item__code--togglable::after{position:absolute;right:0;bottom:-2.5em;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";opacity:0;color:#c4c4c4;font-size:0.8em;transition:0.2s ease-out}.item__code--togglable:hover::after,.item__code--togglable:active::after,.item__code--togglable:focus::after{-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";opacity:1}.item__code--togglable[data-current-state='expanded']::after{content:'Click to collapse.'}.item__code--togglable[data-current-state='collapsed']::after{content:'Click to expand.'}.example__description{padding:1em;background:#EFEFEF}.example__description p{margin:0}.example__code[class*='language-']{margin:0}.item__anchor{font-size:0.6em;color:#eeafb9}@media (min-width: 801px){.item__anchor{position:absolute;right:101%;bottom:0.25em;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";opacity:0}.item:hover .item__anchor{-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";opacity:1}}.item__deprecated{display:inline-block;overflow:hidden;margin-top:5.5em;margin-left:1em}.item__deprecated strong{float:left;color:#c00;text-transform:uppercase}.item__deprecated p{float:left;margin:0;padding-left:0.5em}.item__type{color:#ddd;text-transform:capitalize;font-size:0.75em}.item__alias,.item__aliased{color:#ddd;font-size:0.8em}.item__sub-heading{color:#333;margin-top:0;margin-bottom:1.5rem;font-size:1.2em}.item__parameters{width:100%;margin-bottom:1em;border-collapse:collapse}.item__parameters thead th{vertical-align:bottom;border-bottom:2px solid #ddd;border-top:none;text-align:left;color:#707070}.item__parameters tbody th{text-align:left}.item__parameters td,.item__parameters th{padding:0.5em 0.5em 0.5em 0;vertical-align:top}@media (min-width: 801px){tbody>.item__parameter:first-of-type>td{border-top:none}.item__parameters td,.item__parameters th{border-top:1px solid #ddd}}.item__access{text-transform:capitalize;color:#5c4863;font-size:0.8em}.item__since{float:right;padding-top:0.9em;color:#c4c4c4;margin-bottom:1em}.item__source-link{position:absolute;top:1px;right:1px;background:white;padding:1em;z-index:2;color:#c4c4c4}.item__cross-type{color:#4d4d4d;font-family:'Consolas', 'Monaco', 'Andale Mono', monospace;font-size:0.8em}.item__description{margin-bottom:1.5rem}li.item__description{margin-bottom:0}.item__description--inline>*{display:inline-block;margin:0}.item__code-wrapper{position:relative;clear:both;margin-bottom:1.5rem}.color-preview--inline{padding:2px 4px;border:1px solid rgba(0,0,0,0.1);border-radius:3px}.color-preview--block{width:2em;height:2em;position:absolute;top:140%;right:0;top:calc(100% + 20px);border:1px solid rgba(0,0,0,0.1);border-radius:3px} diff --git a/docs/assets/images/favicon.png b/docs/assets/images/favicon.png new file mode 100644 index 0000000..585fb53 Binary files /dev/null and b/docs/assets/images/favicon.png differ diff --git a/docs/assets/images/logo_full_compact.svg b/docs/assets/images/logo_full_compact.svg new file mode 100644 index 0000000..0f590c9 --- /dev/null +++ b/docs/assets/images/logo_full_compact.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/assets/images/logo_full_inline.svg b/docs/assets/images/logo_full_inline.svg new file mode 100644 index 0000000..68b0103 --- /dev/null +++ b/docs/assets/images/logo_full_inline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/assets/images/logo_light_compact.svg b/docs/assets/images/logo_light_compact.svg new file mode 100644 index 0000000..7f9ef80 --- /dev/null +++ b/docs/assets/images/logo_light_compact.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/assets/images/logo_light_inline.svg b/docs/assets/images/logo_light_inline.svg new file mode 100644 index 0000000..120ffd2 --- /dev/null +++ b/docs/assets/images/logo_light_inline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/assets/js/main.js b/docs/assets/js/main.js new file mode 100644 index 0000000..015842a --- /dev/null +++ b/docs/assets/js/main.js @@ -0,0 +1,56 @@ +/* global document */ + +(function ($, global) { + 'use strict'; + + // Constructor + var App = function (conf) { + this.conf = $.extend({ + // Search module + search: new global.Search(), + + // Sidebar module + sidebar: new global.Sidebar(), + + // Initialisation + init: true + }, conf || {}); + + // Launch the module + if (this.conf.init !== false) { + this.initialize(); + } + }; + + // Initialisation method + App.prototype.initialize = function () { + this.codePreview(); + }; + + // Toggle code preview collapsed/expanded modes + App.prototype.codePreview = function () { + var $item; + var $code; + var switchTo; + + $('.item__code--togglable').on('click', function () { + $item = $(this); + $code = $item.find('code'); + switchTo = $item.attr('data-current-state') === 'expanded' ? 'collapsed' : 'expanded'; + + $item.attr('data-current-state', switchTo); + $code.html($item.attr('data-' + switchTo)); + Prism.highlightElement($code[0]); + }); + }; + + global.App = App; +}(window.jQuery, window)); + +(function ($, global) { + + $(document).ready(function () { + var app = new global.App(); + }); + +}(window.jQuery, window)); \ No newline at end of file diff --git a/docs/assets/js/main.min.js b/docs/assets/js/main.min.js new file mode 100644 index 0000000..b81f9d4 --- /dev/null +++ b/docs/assets/js/main.min.js @@ -0,0 +1 @@ +!function(t){function e(t,n){this.list=t,this.options=n=n||{};var i,o,s;for(i=0,keys=["sort","includeScore","shouldSort"],o=keys.length;o>i;i++)s=keys[i],this.options[s]=s in n?n[s]:e.defaultOptions[s];for(i=0,keys=["searchFn","sortFn","keys","getFn"],o=keys.length;o>i;i++)s=keys[i],this.options[s]=n[s]||e.defaultOptions[s]}var n=function(t,e){if(e=e||{},this.options=e,this.options.location=e.location||n.defaultOptions.location,this.options.distance="distance"in e?e.distance:n.defaultOptions.distance,this.options.threshold="threshold"in e?e.threshold:n.defaultOptions.threshold,this.options.maxPatternLength=e.maxPatternLength||n.defaultOptions.maxPatternLength,this.pattern=e.caseSensitive?t:t.toLowerCase(),this.patternLen=t.length,this.patternLen>this.options.maxPatternLength)throw new Error("Pattern length is too long");this.matchmask=1<'+item.type.slice(0,3)+" "+item.name+""});searchSuggestions.append($li);return $li});return suggestions};Search.prototype.search=function(term){return this.fillSuggestions(this.index.search(term))};Search.prototype.initializeSearch=function(){var searchForm=$(this.conf.search.form);var searchInput=$(this.conf.search.input);var searchSuggestions=$(this.conf.search.suggestionsWrapper);var currentSelection=-1;var suggestions=[];var selected;var self=this;searchSuggestions.on("click",function(e){var target=$(event.target);if(target.nodeName==="A"){searchInput.val(target.parent().data("name"));suggestions=self.fillSuggestions([])}});searchForm.on("keyup",function(e){e.preventDefault();if(e.keyCode===13){if(selected){suggestions=self.fillSuggestions([]);searchInput.val(selected.data("name"));window.location=selected.children().first().attr("href")}e.stopPropagation()}if(e.keyCode===40){currentSelection=(currentSelection+1)%suggestions.length}if(e.keyCode===38){currentSelection=currentSelection-1;if(currentSelection<0){currentSelection=suggestions.length-1}}if(suggestions[currentSelection]){if(selected){selected.removeClass("selected")}selected=suggestions[currentSelection];selected.addClass("selected")}});searchInput.on("keyup",function(e){if(e.keyCode!==40&&e.keyCode!==38){currentSelection=-1;suggestions=self.search($(this).val())}else{e.preventDefault()}}).on("search",function(){suggestions=self.search($(this).val())})};global.Search=Search})(window.jQuery,window);(function($,global){"use strict";var App=function(conf){this.conf=$.extend({search:new global.Search,sidebar:new global.Sidebar,init:true},conf||{});if(this.conf.init!==false){this.initialize()}};App.prototype.initialize=function(){this.codePreview()};App.prototype.codePreview=function(){var $item;var $code;var switchTo;$(".item__code--togglable").on("click",function(){$item=$(this);$code=$item.find("code");switchTo=$item.attr("data-current-state")==="expanded"?"collapsed":"expanded";$item.attr("data-current-state",switchTo);$code.html($item.attr("data-"+switchTo));Prism.highlightElement($code[0])})};global.App=App})(window.jQuery,window);(function($,global){$(document).ready(function(){var app=new global.App})})(window.jQuery,window);var self=typeof window!="undefined"?window:{},Prism=function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{encode:function(e){return e instanceof n?new n(e.type,t.util.encode(e.content)):t.util.type(e)==="Array"?e.map(t.util.encode):e.replace(/&/g,"&").replace(/e.length)break e;if(p instanceof i)continue;a.lastIndex=0;var d=a.exec(p);if(d){l&&(c=d[1].length);var v=d.index-1+c,d=d[0].slice(c),m=d.length,g=v+m,y=p.slice(0,v+1),b=p.slice(g+1),w=[h,1];y&&w.push(y);var E=new i(u,f?t.tokenize(d,f):d);w.push(E);b&&w.push(b);Array.prototype.splice.apply(s,w)}}}return s},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[];r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(!r||!r.length)return;for(var i=0,s;s=r[i++];)s(n)}}},n=t.Token=function(e,t){this.type=e;this.content=t};n.stringify=function(e,r,i){if(typeof e=="string")return e;if(Object.prototype.toString.call(e)=="[object Array]")return e.map(function(t){return n.stringify(t,r,e)}).join("");var s={type:e.type,content:n.stringify(e.content,r,i),tag:"span",classes:["token",e.type],attributes:{},language:r,parent:i};s.type=="comment"&&(s.attributes.spellcheck="true");t.hooks.run("wrap",s);var o="";for(var u in s.attributes)o+=u+'="'+(s.attributes[u]||"")+'"';return"<"+s.tag+' class="'+s.classes.join(" ")+'" '+o+">"+s.content+""+s.tag+">"};if(!self.document){if(!self.addEventListener)return self.Prism;self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,i=n.code;self.postMessage(JSON.stringify(t.tokenize(i,t.languages[r])));self.close()},!1);return self.Prism}var r=document.getElementsByTagName("script");r=r[r.length-1];if(r){t.filename=r.src;document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)}return self.Prism}();typeof module!="undefined"&&module.exports&&(module.exports=Prism);Prism.languages.markup={comment://g,prolog:/<\?.+?\?>/,doctype://,cdata://i,tag:{pattern:/<\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|[^\s'">=]+))?\s*)*\/?>/gi,inside:{tag:{pattern:/^<\/?[\w:-]+/i,inside:{punctuation:/^<\/?/,namespace:/^[\w-]+?:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi,inside:{punctuation:/=|>|"/g}},punctuation:/\/?>/g,"attr-name":{pattern:/[\w:-]+/g,inside:{namespace:/^[\w-]+?:/}}}},entity:/\?[\da-z]{1,8};/gi};Prism.hooks.add("wrap",function(e){e.type==="entity"&&(e.attributes.title=e.content.replace(/&/,"&"))});Prism.languages.css={comment:/\/\*[\w\W]*?\*\//g,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*{))/gi,inside:{punctuation:/[;:]/g}},url:/url\((["']?).*?\1\)/gi,selector:/[^\{\}\s][^\{\};]*(?=\s*\{)/g,property:/(\b|\B)[\w-]+(?=\s*:)/gi,string:/("|')(\\?.)*?\1/g,important:/\B!important\b/gi,punctuation:/[\{\};:]/g,"function":/[-a-z0-9]+(?=\()/gi};Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{style:{pattern:/