SassyJSON 1.0.11 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +1 -0
- data/README.md +17 -1
- data/lib/JsonImporter.rb +229 -0
- data/lib/SassyJSON.rb +2 -2
- metadata +10 -7
- checksums.yaml +0 -7
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -26,7 +26,9 @@ npm install sassyjson --save-dev
|
|
26
26
|
|
27
27
|
### Sass
|
28
28
|
|
29
|
-
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.
|
29
|
+
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.
|
30
|
+
|
31
|
+
Also, SassyJSON is available at [Sassmeister](http://sassmeister.com/).
|
30
32
|
|
31
33
|
## Example
|
32
34
|
|
@@ -69,6 +71,20 @@ $json-decode: json-decode('{"a": [1, 2, {"b": 1}], "b": ["#444444", false, {"a":
|
|
69
71
|
// ("a": 1 2 ("b": 1), "b": #444444 false ("a": 1, "b": "test"), "c": 2 3 4 "string")
|
70
72
|
```
|
71
73
|
|
74
|
+
## Importing and decoding a JSON file
|
75
|
+
|
76
|
+
To importe and decode an external `.json` file directly into a Sass variable:
|
77
|
+
|
78
|
+
``` scss
|
79
|
+
@import 'relative/path/to/file.json?variable-name'
|
80
|
+
// Do something with $variable-name
|
81
|
+
```
|
82
|
+
|
83
|
+
**Important:**
|
84
|
+
|
85
|
+
* the path to the JSON file is relative to importing file
|
86
|
+
* the get parameter is the variable name to use it in Sass
|
87
|
+
|
72
88
|
## Requirements
|
73
89
|
|
74
90
|
All you need is a clean version of Sass 3.3. Otherwise it's just pure Sass madness.
|
data/lib/JsonImporter.rb
ADDED
@@ -0,0 +1,229 @@
|
|
1
|
+
require 'sass'
|
2
|
+
|
3
|
+
|
4
|
+
# Monkey Path Sass
|
5
|
+
# Adapted from: https://github.com/chriseppstein/sass-css-importer
|
6
|
+
class Sass::Engine
|
7
|
+
alias initialize_without_json_importer initialize
|
8
|
+
|
9
|
+
def initialize(template, options={})
|
10
|
+
initialize_without_json_importer(template, options)
|
11
|
+
|
12
|
+
json_importer = self.options[:load_paths].find {|lp| lp.is_a?(Sass::Importers::JsonImporter) }
|
13
|
+
|
14
|
+
unless json_importer
|
15
|
+
root = File.dirname(options[:filename] || ".")
|
16
|
+
self.options[:load_paths] << Sass::Importers::JsonImporter.new(root)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module Sass
|
22
|
+
module Importers
|
23
|
+
# The default importer, used for any strings found in the load path.
|
24
|
+
# Simply loads Sass files from the filesystem using the default logic.
|
25
|
+
class JsonImporter < Base
|
26
|
+
|
27
|
+
attr_accessor :root
|
28
|
+
|
29
|
+
# Creates a new filesystem importer that imports files relative to a given path.
|
30
|
+
#
|
31
|
+
# @param root [String] The root path.
|
32
|
+
# This importer will import files relative to this path.
|
33
|
+
def initialize(root)
|
34
|
+
@root = File.expand_path(root)
|
35
|
+
@same_name_warnings = Set.new
|
36
|
+
end
|
37
|
+
|
38
|
+
# Enable watching of json files in Sass 3.3+
|
39
|
+
def watched_directories
|
40
|
+
[root]
|
41
|
+
end
|
42
|
+
|
43
|
+
# Enable watching of json files in Sass 3.3+
|
44
|
+
def watched_file?(file)
|
45
|
+
file.start_with?(root+File::SEPARATOR) && File.extname(file) == ".json"
|
46
|
+
end
|
47
|
+
# @see Base#find_relative
|
48
|
+
def find_relative(name, base, options)
|
49
|
+
_find(File.dirname(base), name, options)
|
50
|
+
end
|
51
|
+
|
52
|
+
# @see Base#find
|
53
|
+
def find(name, options)
|
54
|
+
_find(@root, name, options)
|
55
|
+
end
|
56
|
+
|
57
|
+
# @see Base#mtime
|
58
|
+
def mtime(name, options)
|
59
|
+
name = strip_varname(name);
|
60
|
+
file, _ = Sass::Util.destructure(find_real_file(@root, name, options))
|
61
|
+
File.mtime(file) if file
|
62
|
+
rescue Errno::ENOENT
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
|
66
|
+
# @see Base#key
|
67
|
+
def key(name, options)
|
68
|
+
name = strip_varname(name);
|
69
|
+
[self.class.name + ":" + File.dirname(File.expand_path(name)),
|
70
|
+
File.basename(name)]
|
71
|
+
end
|
72
|
+
|
73
|
+
# @see Base#to_s
|
74
|
+
def to_s
|
75
|
+
@root
|
76
|
+
end
|
77
|
+
|
78
|
+
def hash
|
79
|
+
@root.hash
|
80
|
+
end
|
81
|
+
|
82
|
+
def eql?(other)
|
83
|
+
root.eql?(other.root)
|
84
|
+
end
|
85
|
+
|
86
|
+
protected
|
87
|
+
|
88
|
+
# If a full uri is passed, this removes the root from it
|
89
|
+
# otherwise returns the name unchanged
|
90
|
+
def remove_root(name)
|
91
|
+
if name.index(@root + "/") == 0
|
92
|
+
name[(@root.length + 1)..-1]
|
93
|
+
else
|
94
|
+
name
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# A hash from file extensions to the syntaxes for those extensions.
|
99
|
+
# The syntaxes must be `:sass` or `:scss`.
|
100
|
+
#
|
101
|
+
# This can be overridden by subclasses that want normal filesystem importing
|
102
|
+
# with unusual extensions.
|
103
|
+
#
|
104
|
+
# @return [{String => Symbol}]
|
105
|
+
def extensions
|
106
|
+
{'json' => :scss}
|
107
|
+
end
|
108
|
+
|
109
|
+
# Given an `@import`ed path, returns an array of possible
|
110
|
+
# on-disk filenames and their corresponding syntaxes for that path.
|
111
|
+
#
|
112
|
+
# @param name [String] The filename.
|
113
|
+
# @return [Array(String, Symbol)] An array of pairs.
|
114
|
+
# The first element of each pair is a filename to look for;
|
115
|
+
# the second element is the syntax that file would be in (`:sass` or `:scss`).
|
116
|
+
def possible_files(name)
|
117
|
+
name = escape_glob_characters(name)
|
118
|
+
dirname, basename, extname = split(name)
|
119
|
+
sorted_exts = extensions.sort
|
120
|
+
syntax = extensions[extname]
|
121
|
+
|
122
|
+
if syntax
|
123
|
+
ret = [["#{dirname}/{_,}#{basename}.#{extensions.invert[syntax]}", syntax]]
|
124
|
+
else
|
125
|
+
ret = sorted_exts.map {|ext, syn| ["#{dirname}/{_,}#{basename}.#{ext}", syn]}
|
126
|
+
end
|
127
|
+
|
128
|
+
# JRuby chokes when trying to import files from JARs when the path starts with './'.
|
129
|
+
ret.map {|f, s| [f.sub(%r{^\./}, ''), s]}
|
130
|
+
end
|
131
|
+
|
132
|
+
def escape_glob_characters(name)
|
133
|
+
name.gsub(/[\*\[\]\{\}\?]/) do |char|
|
134
|
+
"\\#{char}"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
REDUNDANT_DIRECTORY = %r{#{Regexp.escape(File::SEPARATOR)}\.#{Regexp.escape(File::SEPARATOR)}}
|
139
|
+
# Given a base directory and an `@import`ed name,
|
140
|
+
# finds an existant file that matches the name.
|
141
|
+
#
|
142
|
+
# @param dir [String] The directory relative to which to search.
|
143
|
+
# @param name [String] The filename to search for.
|
144
|
+
# @return [(String, Symbol)] A filename-syntax pair.
|
145
|
+
def find_real_file(dir, name, options)
|
146
|
+
# on windows 'dir' can be in native File::ALT_SEPARATOR form
|
147
|
+
dir = dir.gsub(File::ALT_SEPARATOR, File::SEPARATOR) unless File::ALT_SEPARATOR.nil?
|
148
|
+
|
149
|
+
found = possible_files(remove_root(name)).map do |f, s|
|
150
|
+
path = (dir == "." || Pathname.new(f).absolute?) ? f : "#{escape_glob_characters(dir)}/#{f}"
|
151
|
+
Dir[path].map do |full_path|
|
152
|
+
full_path.gsub!(REDUNDANT_DIRECTORY, File::SEPARATOR)
|
153
|
+
[Pathname.new(full_path).cleanpath.to_s, s]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
found = Sass::Util.flatten(found, 1)
|
157
|
+
return if found.empty?
|
158
|
+
|
159
|
+
if found.size > 1 && !@same_name_warnings.include?(found.first.first)
|
160
|
+
found.each {|(f, _)| @same_name_warnings << f}
|
161
|
+
relative_to = Pathname.new(dir)
|
162
|
+
if options[:_line]
|
163
|
+
# If _line exists, we're here due to an actual import in an
|
164
|
+
# import_node and we want to print a warning for a user writing an
|
165
|
+
# ambiguous import.
|
166
|
+
candidates = found.map {|(f, _)| " " + Pathname.new(f).relative_path_from(relative_to).to_s}.join("\n")
|
167
|
+
Sass::Util.sass_warn <<WARNING
|
168
|
+
WARNING: On line #{options[:_line]}#{" of #{options[:filename]}" if options[:filename]}:
|
169
|
+
It's not clear which file to import for '@import "#{name}"'.
|
170
|
+
Candidates:
|
171
|
+
#{candidates}
|
172
|
+
For now I'll choose #{File.basename found.first.first}.
|
173
|
+
This will be an error in future versions of Sass.
|
174
|
+
WARNING
|
175
|
+
else
|
176
|
+
# Otherwise, we're here via StalenessChecker, and we want to print a
|
177
|
+
# warning for a user running `sass --watch` with two ambiguous files.
|
178
|
+
candidates = found.map {|(f, _)| " " + File.basename(f)}.join("\n")
|
179
|
+
Sass::Util.sass_warn <<WARNING
|
180
|
+
WARNING: In #{File.dirname(name)}:
|
181
|
+
There are multiple files that match the name "#{File.basename(name)}":
|
182
|
+
#{candidates}
|
183
|
+
WARNING
|
184
|
+
end
|
185
|
+
end
|
186
|
+
found.first
|
187
|
+
end
|
188
|
+
|
189
|
+
# Splits a filename into three parts, a directory part, a basename, and an extension
|
190
|
+
# Only the known extensions returned from the extensions method will be recognized as such.
|
191
|
+
def split(name)
|
192
|
+
extension = nil
|
193
|
+
dirname, basename = File.dirname(name), File.basename(name)
|
194
|
+
if basename =~ /^(.*)\.(#{extensions.keys.map{|e| Regexp.escape(e)}.join('|')})$/
|
195
|
+
basename = $1
|
196
|
+
extension = $2
|
197
|
+
end
|
198
|
+
[dirname, basename, extension]
|
199
|
+
end
|
200
|
+
|
201
|
+
private
|
202
|
+
|
203
|
+
def strip_varname(name)
|
204
|
+
name.include?(".json?") ? name[0..name.rindex("?")-1] : name
|
205
|
+
end
|
206
|
+
|
207
|
+
|
208
|
+
def _find(dir, name, options)
|
209
|
+
if name.include? ".json?"
|
210
|
+
quotePos = name.rindex("?");
|
211
|
+
path = name[0..quotePos-1]
|
212
|
+
varname = name[quotePos+1..-1]
|
213
|
+
|
214
|
+
full_filename, syntax = Sass::Util.destructure(find_real_file(dir, path, options))
|
215
|
+
return unless full_filename && File.readable?(full_filename)
|
216
|
+
|
217
|
+
options[:syntax] = syntax
|
218
|
+
options[:filename] = full_filename
|
219
|
+
options[:importer] = self
|
220
|
+
|
221
|
+
Sass::Engine.new("$#{varname} : json_decode('" + File.read(full_filename) + "');", options)
|
222
|
+
else
|
223
|
+
Sass::Engine.new("$hello:'test';", options)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
data/lib/SassyJSON.rb
CHANGED
@@ -5,8 +5,8 @@ Compass::Frameworks.register('SassyJSON', :path => extension_path)
|
|
5
5
|
# Version is a number. If a version contains alphas, it will be created as a prerelease version
|
6
6
|
# Date is in the form of YYYY-MM-DD
|
7
7
|
module SassyJSON
|
8
|
-
VERSION = "1.0
|
9
|
-
DATE = "2014-01-
|
8
|
+
VERSION = "1.1.0"
|
9
|
+
DATE = "2014-01-29"
|
10
10
|
end
|
11
11
|
|
12
12
|
module Sass::Script::Functions
|
metadata
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: SassyJSON
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Hugo Giraudel
|
@@ -9,7 +10,7 @@ authors:
|
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date: 2014-01-
|
13
|
+
date: 2014-01-29 00:00:00.000000000 Z
|
13
14
|
dependencies: []
|
14
15
|
description: Sass API for JSON
|
15
16
|
email:
|
@@ -21,6 +22,7 @@ extra_rdoc_files: []
|
|
21
22
|
files:
|
22
23
|
- README.md
|
23
24
|
- CHANGELOG.md
|
25
|
+
- lib/JsonImporter.rb
|
24
26
|
- lib/SassyJSON.rb
|
25
27
|
- stylesheets/decode/api/_json.scss
|
26
28
|
- stylesheets/decode/decode.scss
|
@@ -60,26 +62,27 @@ files:
|
|
60
62
|
- stylesheets/SassyJSON.scss
|
61
63
|
homepage: https://github.com/HugoGiraudel/SassyJSON/
|
62
64
|
licenses: []
|
63
|
-
metadata: {}
|
64
65
|
post_install_message:
|
65
66
|
rdoc_options: []
|
66
67
|
require_paths:
|
67
68
|
- lib
|
68
69
|
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
69
71
|
requirements:
|
70
|
-
- - '>='
|
72
|
+
- - ! '>='
|
71
73
|
- !ruby/object:Gem::Version
|
72
74
|
version: '0'
|
73
75
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
74
77
|
requirements:
|
75
|
-
- - '>='
|
78
|
+
- - ! '>='
|
76
79
|
- !ruby/object:Gem::Version
|
77
80
|
version: 1.3.6
|
78
81
|
requirements: []
|
79
82
|
rubyforge_project: SassyJSON
|
80
|
-
rubygems_version:
|
83
|
+
rubygems_version: 1.8.24
|
81
84
|
signing_key:
|
82
|
-
specification_version:
|
85
|
+
specification_version: 3
|
83
86
|
summary: SassyJSON is a Sass-powered API for JSON. It provides you the classic json-encode
|
84
87
|
and json-decode directly from your Sass files.
|
85
88
|
test_files: []
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: b252de6ac6970e21a3b2cdcdfecbc263064be64d
|
4
|
-
data.tar.gz: 98888fa1e6ace45183f65b96809eb4945a211376
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: ed3b1b5469126f55682340b2f0957ff2bcc13faa9c289a280e35c3a4c97c960627b50941378dd1dfa1c5e611719627be10151946b849e91762d94e54cad492b0
|
7
|
-
data.tar.gz: c319e4e58baa7e2cd4316a227ac2809eb6a9ae67fb9e413ad537e65298b81d18b5c97c13358d2afa94216d02ce9274b9e10cedb709a6aedb87ba596c666e94b1
|