diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 920eeb6..8f18c2e 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -14,7 +14,7 @@ Metrics/AbcSize: # Offense count: 2 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 208 + Max: 217 # Offense count: 3 # Configuration parameters: AllowedMethods, AllowedPatterns. diff --git a/lib/glug/layer.rb b/lib/glug/layer.rb index 39ff310..d98bedf 100644 --- a/lib/glug/layer.rb +++ b/lib/glug/layer.rb @@ -82,7 +82,23 @@ def initialize(stylesheet, args = {}) end def dsl_eval(&block) + # Copy ivars from stylesheet DSL to layer DSL (before eval) + style_dsl = @stylesheet.dsl + style_dsl.instance_variables.each do |ivar| + next if ivar.to_s.start_with?('@__') # skip internal ivars + + @dsl.instance_variable_set(ivar, style_dsl.instance_variable_get(ivar)) + end + + # Run the layer evaluation @dsl.instance_eval(&block) + + # Copy ivars back to stylesheet DSL (after eval) + @dsl.instance_variables.each do |ivar| + next if ivar.to_s.start_with?('@__') # skip internal ivars + + style_dsl.instance_variable_set(ivar, @dsl.instance_variable_get(ivar)) + end end # Handle all missing 'method' calls diff --git a/lib/glug/stylesheet.rb b/lib/glug/stylesheet.rb index 8223f19..0b5a334 100644 --- a/lib/glug/stylesheet.rb +++ b/lib/glug/stylesheet.rb @@ -3,7 +3,7 @@ module Glug # the main document object class Stylesheet - attr_accessor :sources, :kv, :base_dir, :params + attr_accessor :sources, :kv, :base_dir, :params, :dsl def initialize(base_dir: nil, params: nil, &block) @sources = {} diff --git a/lib/glug/stylesheet_dsl.rb b/lib/glug/stylesheet_dsl.rb index 12361f5..9590090 100644 --- a/lib/glug/stylesheet_dsl.rb +++ b/lib/glug/stylesheet_dsl.rb @@ -26,7 +26,11 @@ def respond_to_missing?(*) # Set a property, e.g. 'bearing 29' def method_missing(method_sym, *args) - @__impl.add_property(method_sym, *args) + if Layer::EXPRESSIONS.include?(method_sym) + Condition.new.from_list(method_sym, args) + else + @__impl.add_property(method_sym, *args) + end end end end diff --git a/spec/fixtures/expression_ivars.glug b/spec/fixtures/expression_ivars.glug new file mode 100644 index 0000000..ea17541 --- /dev/null +++ b/spec/fixtures/expression_ivars.glug @@ -0,0 +1,12 @@ +version 8 +name 'Expression ivars test' +source :shortbread, type: 'vector', url: 'https://vector.openstreetmap.org/shortbread_v1/tilejson.json' + +# Expression assigned to ivar at stylesheet level +@my_halo = rgba(255, 255, 255, 0.8) +@my_color = rgb(100, 200, 50) + +layer(:labels, zoom: 5.., source: :shortbread) do + text_halo_color @my_halo + text_color @my_color +end diff --git a/spec/fixtures/expression_ivars.json b/spec/fixtures/expression_ivars.json new file mode 100644 index 0000000..ccf97c9 --- /dev/null +++ b/spec/fixtures/expression_ivars.json @@ -0,0 +1,23 @@ +{ + "version":8, + "name":"Expression ivars test", + "sources":{ + "shortbread":{ + "type":"vector", + "url":"https://vector.openstreetmap.org/shortbread_v1/tilejson.json" + } + }, + "layers":[ + { + "paint":{ + "text-halo-color":["rgba",255,255,255,0.8], + "text-color":["rgb",100,200,50] + }, + "source":"shortbread", + "id":"labels", + "source-layer":"labels", + "type":"symbol", + "minzoom":5 + } + ] +} \ No newline at end of file diff --git a/spec/fixtures/ivars.glug b/spec/fixtures/ivars.glug new file mode 100644 index 0000000..4f90f91 --- /dev/null +++ b/spec/fixtures/ivars.glug @@ -0,0 +1,23 @@ +version 8 +name 'My first stylesheet' +source :shortbread, type: 'vector', url: 'https://vector.openstreetmap.org/shortbread_v1/tilejson.json' + +# set at stylesheet level +@width = 6 + +layer(:roads, zoom: 10..13, source: :shortbread) do + # get at layer level + line_width @width + line_color 0x888888 +end + +layer(:water, source: :shortbread) do + # set at layer level + @water = 'blue' + fill_color @water +end + +layer(:water_line, source: :shortbread) do + # get from other layer + fill_color @water +end diff --git a/spec/fixtures/ivars.json b/spec/fixtures/ivars.json new file mode 100644 index 0000000..14669b8 --- /dev/null +++ b/spec/fixtures/ivars.json @@ -0,0 +1,35 @@ +{ + "version":8, + "name":"My first stylesheet", + "sources":{ + "shortbread":{ + "type":"vector", + "url":"https://vector.openstreetmap.org/shortbread_v1/tilejson.json" + } + }, + "layers":[ + { + "paint":{"line-width":6,"line-color":"#888888"}, + "source":"shortbread", + "id":"roads", + "source-layer":"roads", + "type":"line", + "minzoom":10, + "maxzoom":13 + }, + { + "paint":{"fill-color":"blue"}, + "source":"shortbread", + "id":"water", + "source-layer":"water", + "type":"fill" + }, + { + "paint":{"fill-color":"blue"}, + "source":"shortbread", + "id":"water_line", + "source-layer":"water_line", + "type":"fill" + } + ] +} diff --git a/spec/fixtures/ivars_with_include.glug b/spec/fixtures/ivars_with_include.glug new file mode 100644 index 0000000..4b612a8 --- /dev/null +++ b/spec/fixtures/ivars_with_include.glug @@ -0,0 +1,8 @@ +version 8 +name 'My first stylesheet' +source :shortbread, type: 'vector', url: 'https://vector.openstreetmap.org/shortbread_v1/tilejson.json' + +# set at stylesheet level +@width = 6 + +include_file 'ivars_with_include_sub.glug' diff --git a/spec/fixtures/ivars_with_include.json b/spec/fixtures/ivars_with_include.json new file mode 100644 index 0000000..62083cf --- /dev/null +++ b/spec/fixtures/ivars_with_include.json @@ -0,0 +1,21 @@ +{ + "version":8, + "name":"My first stylesheet", + "sources":{ + "shortbread":{ + "type":"vector", + "url":"https://vector.openstreetmap.org/shortbread_v1/tilejson.json" + } + }, + "layers":[ + { + "paint":{"line-width":6,"line-color":"#888888"}, + "source":"shortbread", + "id":"roads", + "source-layer":"roads", + "type":"line", + "minzoom":10, + "maxzoom":13 + } + ] +} diff --git a/spec/fixtures/ivars_with_include_sub.glug b/spec/fixtures/ivars_with_include_sub.glug new file mode 100644 index 0000000..21c6a99 --- /dev/null +++ b/spec/fixtures/ivars_with_include_sub.glug @@ -0,0 +1,4 @@ +layer(:roads, zoom: 10..13, source: :shortbread) do + line_width @width + line_color 0x888888 +end diff --git a/spec/lib/glug/stylesheet_spec.rb b/spec/lib/glug/stylesheet_spec.rb index c3654fc..f25811e 100644 --- a/spec/lib/glug/stylesheet_spec.rb +++ b/spec/lib/glug/stylesheet_spec.rb @@ -86,5 +86,32 @@ output = File.read(File.join(fixture_dir, 'basic_with_include.json')) expect(stylesheet.to_json).to eql(output.strip) end + + it 'sets and gets instance variables across the whole stylesheet' do + glug = File.read(File.join(fixture_dir, 'ivars.glug')) + stylesheet = described_class.new(base_dir: fixture_dir) do + instance_eval(glug) + end + output = File.read(File.join(fixture_dir, 'ivars.json')) + expect(stylesheet.to_json).to eql(output.strip) + end + + it 'sets and gets instance variables across included stylesheets' do + glug = File.read(File.join(fixture_dir, 'ivars_with_include.glug')) + stylesheet = described_class.new(base_dir: fixture_dir) do + instance_eval(glug) + end + output = File.read(File.join(fixture_dir, 'ivars_with_include.json')) + expect(stylesheet.to_json).to eql(output.strip) + end + + it 'stores expressions in ivars at stylesheet level' do + glug = File.read(File.join(fixture_dir, 'expression_ivars.glug')) + stylesheet = described_class.new(base_dir: fixture_dir) do + instance_eval(glug) + end + output = File.read(File.join(fixture_dir, 'expression_ivars.json')) + expect(stylesheet.to_json).to eql(output.strip) + end end end