phlex 1.0.0.rc1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of phlex might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/Gemfile +1 -0
- data/SECURITY.md +10 -2
- data/lib/phlex/collection.rb +1 -3
- data/lib/phlex/configuration.rb +7 -1
- data/lib/phlex/experimental.rb +4 -1
- data/lib/phlex/helpers.rb +26 -15
- data/lib/phlex/html.rb +76 -36
- data/lib/phlex/table.rb +7 -9
- data/lib/phlex/version.rb +1 -1
- data/lib/phlex.rb +1 -1
- metadata +4 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: e074c926f013d613e2523b41c8dd604758d087c64d377b50a343c651b0164c0d
         | 
| 4 | 
            +
              data.tar.gz: 56019e811dff06ef053adfeb20160fe29c247ee2e2f37848eba1580d240c41fd
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 24489ae7f67415aa23ce258d6a121fe37418ce32e543888410b730821feeafd5fda6f164dd6f390f9dd4a0ec7a8a92ae5c50deb53376f95f987203ad4da2acf2
         | 
| 7 | 
            +
              data.tar.gz: 1ddfa0b6dff09c597cec5f77f521faf89344981e4f3ddd3237722d94cb4d4faeec0d385a7ef4a0a18acec770d7f22811ac489ae94dfdfc3fc92fbf1cbb676f20
         | 
    
        data/.rubocop.yml
    CHANGED
    
    
    
        data/Gemfile
    CHANGED
    
    
    
        data/SECURITY.md
    CHANGED
    
    | @@ -1,5 +1,13 @@ | |
| 1 1 | 
             
            # Security Policy
         | 
| 2 2 |  | 
| 3 | 
            -
            ## Reporting a  | 
| 3 | 
            +
            ## Reporting a vulnerability
         | 
| 4 4 |  | 
| 5 | 
            -
            If you  | 
| 5 | 
            +
            If you find a possible security vulnerability, please email security@phlex.fun. Do not create an issue or pull request either demonstrating or fixing the vulnerability.
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            ## Bug bounty
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            [The Gem Foundation](https://ryanbigg.com/2022/11/the-gem-foundation) has kindly sponsored a $1 bug bounty to discover security vulnerabilities in Phlex.
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            ## Sponsoring a bug bounty
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            If you wish to sponsor a bug bounty for Phlex, please get in touch with Joel at joel@drapper.me.
         | 
    
        data/lib/phlex/collection.rb
    CHANGED
    
    | @@ -17,9 +17,7 @@ module Phlex | |
| 17 17 | 
             
            			@item ? item_template : collection_template { yield_items }
         | 
| 18 18 | 
             
            		end
         | 
| 19 19 |  | 
| 20 | 
            -
            		private
         | 
| 21 | 
            -
             | 
| 22 | 
            -
            		def yield_items
         | 
| 20 | 
            +
            		private def yield_items
         | 
| 23 21 | 
             
            			if @item
         | 
| 24 22 | 
             
            				raise ArgumentError, "You can only yield_items when rendering a collection. You are currently rendering an item."
         | 
| 25 23 | 
             
            			end
         | 
    
        data/lib/phlex/configuration.rb
    CHANGED
    
    
    
        data/lib/phlex/experimental.rb
    CHANGED
    
    | @@ -3,7 +3,10 @@ | |
| 3 3 | 
             
            module Phlex
         | 
| 4 4 | 
             
            	module Experimental
         | 
| 5 5 | 
             
            		def before_template
         | 
| 6 | 
            -
            			 | 
| 6 | 
            +
            			if Phlex.configuration.experimental_warnings
         | 
| 7 | 
            +
            				puts "Warning: #{self.class.name} is experimental and subject to change."
         | 
| 8 | 
            +
            			end
         | 
| 9 | 
            +
             | 
| 7 10 | 
             
            			super
         | 
| 8 11 | 
             
            		end
         | 
| 9 12 | 
             
            	end
         | 
    
        data/lib/phlex/helpers.rb
    CHANGED
    
    | @@ -5,30 +5,41 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.0") | |
| 5 5 | 
             
            end
         | 
| 6 6 |  | 
| 7 7 | 
             
            module Phlex::Helpers
         | 
| 8 | 
            -
            	private
         | 
| 9 | 
            -
             | 
| 10 | 
            -
            	def tokens(*tokens, **conditional_tokens)
         | 
| 8 | 
            +
            	private def tokens(*tokens, **conditional_tokens)
         | 
| 11 9 | 
             
            		conditional_tokens.each do |condition, token|
         | 
| 12 | 
            -
            			case condition
         | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
            				"The class condition must be a Symbol or a Proc."
         | 
| 10 | 
            +
            			truthy = case condition
         | 
| 11 | 
            +
            				when Symbol then send(condition)
         | 
| 12 | 
            +
            				when Proc then condition.call
         | 
| 13 | 
            +
            				else raise ArgumentError, "The class condition must be a Symbol or a Proc."
         | 
| 17 14 | 
             
            			end
         | 
| 18 15 |  | 
| 19 | 
            -
            			 | 
| 20 | 
            -
             | 
| 16 | 
            +
            			if truthy
         | 
| 17 | 
            +
            				case token
         | 
| 18 | 
            +
            					when Hash then _append_token(tokens, token[:then])
         | 
| 19 | 
            +
            					else _append_token(tokens, token)
         | 
| 20 | 
            +
            				end
         | 
| 21 | 
            +
            			else
         | 
| 22 | 
            +
            				case token
         | 
| 23 | 
            +
            					when Hash then _append_token(tokens, token[:else])
         | 
| 24 | 
            +
            				end
         | 
| 25 | 
            +
            			end
         | 
| 26 | 
            +
            		end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            		tokens.join(" ")
         | 
| 29 | 
            +
            	end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            	private def _append_token(tokens, token)
         | 
| 32 | 
            +
            		case token
         | 
| 33 | 
            +
            			when nil then nil
         | 
| 21 34 | 
             
            			when String then tokens << token
         | 
| 35 | 
            +
            			when Symbol then tokens << token.name
         | 
| 22 36 | 
             
            			when Array then tokens.concat(token)
         | 
| 23 37 | 
             
            			else raise ArgumentError,
         | 
| 24 38 | 
             
            				"Conditional classes must be Symbols, Strings, or Arrays of Symbols or Strings."
         | 
| 25 | 
            -
            			end
         | 
| 26 39 | 
             
            		end
         | 
| 27 | 
            -
             | 
| 28 | 
            -
            		tokens.compact.join(" ")
         | 
| 29 40 | 
             
            	end
         | 
| 30 41 |  | 
| 31 | 
            -
            	def classes(*tokens, **conditional_tokens)
         | 
| 42 | 
            +
            	private def classes(*tokens, **conditional_tokens)
         | 
| 32 43 | 
             
            		tokens = self.tokens(*tokens, **conditional_tokens)
         | 
| 33 44 |  | 
| 34 45 | 
             
            		if tokens.empty?
         | 
| @@ -38,7 +49,7 @@ module Phlex::Helpers | |
| 38 49 | 
             
            		end
         | 
| 39 50 | 
             
            	end
         | 
| 40 51 |  | 
| 41 | 
            -
            	def mix(*args)
         | 
| 52 | 
            +
            	private def mix(*args)
         | 
| 42 53 | 
             
            		args.each_with_object({}) do |object, result|
         | 
| 43 54 | 
             
            			result.merge!(object) do |_key, old, new|
         | 
| 44 55 | 
             
            				case new
         | 
    
        data/lib/phlex/html.rb
    CHANGED
    
    | @@ -136,14 +136,23 @@ module Phlex | |
| 136 136 | 
             
            		def call(buffer = +"", view_context: nil, parent: nil, &block)
         | 
| 137 137 | 
             
            			return buffer unless render?
         | 
| 138 138 |  | 
| 139 | 
            -
            			raise "The same view instance shouldn't be rendered twice" if rendered?
         | 
| 140 | 
            -
             | 
| 141 | 
            -
            			@_rendered = true
         | 
| 142 139 | 
             
            			@_target = buffer
         | 
| 143 140 | 
             
            			@_view_context = view_context
         | 
| 144 141 | 
             
            			@_parent = parent
         | 
| 145 142 |  | 
| 146 | 
            -
            			around_template  | 
| 143 | 
            +
            			around_template do
         | 
| 144 | 
            +
            				if block_given?
         | 
| 145 | 
            +
            					template do |*args|
         | 
| 146 | 
            +
            						if args.length > 0
         | 
| 147 | 
            +
            							yield_content_with_args(*args, &block)
         | 
| 148 | 
            +
            						else
         | 
| 149 | 
            +
            							yield_content(&block)
         | 
| 150 | 
            +
            						end
         | 
| 151 | 
            +
            					end
         | 
| 152 | 
            +
            				else
         | 
| 153 | 
            +
            					template
         | 
| 154 | 
            +
            				end
         | 
| 155 | 
            +
            			end
         | 
| 147 156 |  | 
| 148 157 | 
             
            			self.class.rendered_at_least_once ||= true
         | 
| 149 158 |  | 
| @@ -151,10 +160,13 @@ module Phlex | |
| 151 160 | 
             
            		end
         | 
| 152 161 |  | 
| 153 162 | 
             
            		def render(renderable, *args, **kwargs, &block)
         | 
| 154 | 
            -
            			 | 
| 163 | 
            +
            			case renderable
         | 
| 164 | 
            +
            			when Phlex::HTML
         | 
| 155 165 | 
             
            				renderable.call(@_target, view_context: @_view_context, parent: self, &block)
         | 
| 156 | 
            -
            			 | 
| 157 | 
            -
            				 | 
| 166 | 
            +
            			when Class
         | 
| 167 | 
            +
            				if renderable < Phlex::HTML
         | 
| 168 | 
            +
            					renderable.new.call(@_target, view_context: @_view_context, parent: self, &block)
         | 
| 169 | 
            +
            				end
         | 
| 158 170 | 
             
            			else
         | 
| 159 171 | 
             
            				raise ArgumentError, "You can't render a #{renderable}."
         | 
| 160 172 | 
             
            			end
         | 
| @@ -166,14 +178,6 @@ module Phlex | |
| 166 178 | 
             
            			:html
         | 
| 167 179 | 
             
            		end
         | 
| 168 180 |  | 
| 169 | 
            -
            		def rendered?
         | 
| 170 | 
            -
            			@_rendered ||= false
         | 
| 171 | 
            -
            		end
         | 
| 172 | 
            -
             | 
| 173 | 
            -
            		def render?
         | 
| 174 | 
            -
            			true
         | 
| 175 | 
            -
            		end
         | 
| 176 | 
            -
             | 
| 177 181 | 
             
            		STANDARD_ELEMENTS.each do |method_name, tag|
         | 
| 178 182 | 
             
            			register_element(method_name, tag: tag)
         | 
| 179 183 | 
             
            		end
         | 
| @@ -183,14 +187,14 @@ module Phlex | |
| 183 187 | 
             
            		end
         | 
| 184 188 |  | 
| 185 189 | 
             
            		def text(content)
         | 
| 186 | 
            -
            			 | 
| 187 | 
            -
             | 
| 188 | 
            -
             | 
| 189 | 
            -
             | 
| 190 | 
            -
             | 
| 191 | 
            -
             | 
| 192 | 
            -
            				 | 
| 193 | 
            -
            			 | 
| 190 | 
            +
            			@_target << ERB::Util.html_escape(
         | 
| 191 | 
            +
            				case content
         | 
| 192 | 
            +
            					when String then content
         | 
| 193 | 
            +
            					when Symbol then content.name
         | 
| 194 | 
            +
            					when Integer, Float then content.to_s
         | 
| 195 | 
            +
            					else format_object(content) || content.to_s
         | 
| 196 | 
            +
            				end
         | 
| 197 | 
            +
            			)
         | 
| 194 198 |  | 
| 195 199 | 
             
            			nil
         | 
| 196 200 | 
             
            		end
         | 
| @@ -238,23 +242,30 @@ module Phlex | |
| 238 242 | 
             
            			new_buffer
         | 
| 239 243 | 
             
            		end
         | 
| 240 244 |  | 
| 241 | 
            -
            		 | 
| 245 | 
            +
            		# Default render predicate can be overridden to prevent rendering
         | 
| 246 | 
            +
            		private def render?
         | 
| 247 | 
            +
            			true
         | 
| 248 | 
            +
            		end
         | 
| 249 | 
            +
             | 
| 250 | 
            +
            		private def format_object(oject)
         | 
| 251 | 
            +
            			nil
         | 
| 252 | 
            +
            		end
         | 
| 242 253 |  | 
| 243 | 
            -
            		def around_template
         | 
| 254 | 
            +
            		private def around_template
         | 
| 244 255 | 
             
            			before_template
         | 
| 245 256 | 
             
            			yield
         | 
| 246 257 | 
             
            			after_template
         | 
| 247 258 | 
             
            		end
         | 
| 248 259 |  | 
| 249 | 
            -
            		def before_template
         | 
| 260 | 
            +
            		private def before_template
         | 
| 250 261 | 
             
            			nil
         | 
| 251 262 | 
             
            		end
         | 
| 252 263 |  | 
| 253 | 
            -
            		def after_template
         | 
| 264 | 
            +
            		private def after_template
         | 
| 254 265 | 
             
            			nil
         | 
| 255 266 | 
             
            		end
         | 
| 256 267 |  | 
| 257 | 
            -
            		def yield_content(&block)
         | 
| 268 | 
            +
            		private def yield_content(&block)
         | 
| 258 269 | 
             
            			return unless block_given?
         | 
| 259 270 |  | 
| 260 271 | 
             
            			original_length = @_target.length
         | 
| @@ -264,18 +275,47 @@ module Phlex | |
| 264 275 | 
             
            			if unchanged
         | 
| 265 276 | 
             
            				case content
         | 
| 266 277 | 
             
            				when String
         | 
| 267 | 
            -
            					@_target <<  | 
| 278 | 
            +
            					@_target << ERB::Util.html_escape(content)
         | 
| 268 279 | 
             
            				when Symbol
         | 
| 269 | 
            -
            					@_target <<  | 
| 280 | 
            +
            					@_target << ERB::Util.html_escape(content.name)
         | 
| 270 281 | 
             
            				when Integer, Float
         | 
| 271 | 
            -
            					@_target <<  | 
| 282 | 
            +
            					@_target << ERB::Util.html_escape(content.to_s)
         | 
| 283 | 
            +
            				else
         | 
| 284 | 
            +
            					if (formatted_object = format_object(content))
         | 
| 285 | 
            +
            						@_target << ERB::Util.html_escape(formatted_object)
         | 
| 286 | 
            +
            					end
         | 
| 287 | 
            +
            				end
         | 
| 288 | 
            +
            			end
         | 
| 289 | 
            +
             | 
| 290 | 
            +
            			nil
         | 
| 291 | 
            +
            		end
         | 
| 292 | 
            +
             | 
| 293 | 
            +
            		private def yield_content_with_args(*args, &block)
         | 
| 294 | 
            +
            			return unless block_given?
         | 
| 295 | 
            +
             | 
| 296 | 
            +
            			original_length = @_target.length
         | 
| 297 | 
            +
            			content = yield(*args)
         | 
| 298 | 
            +
            			unchanged = (original_length == @_target.length)
         | 
| 299 | 
            +
             | 
| 300 | 
            +
            			if unchanged
         | 
| 301 | 
            +
            				case content
         | 
| 302 | 
            +
            				when String
         | 
| 303 | 
            +
            					@_target << ERB::Util.html_escape(content)
         | 
| 304 | 
            +
            				when Symbol
         | 
| 305 | 
            +
            					@_target << ERB::Util.html_escape(content.name)
         | 
| 306 | 
            +
            				when Integer, Float
         | 
| 307 | 
            +
            					@_target << ERB::Util.html_escape(content.to_s)
         | 
| 308 | 
            +
            				else
         | 
| 309 | 
            +
            					if (formatted_object = format_object(content))
         | 
| 310 | 
            +
            						@_target << ERB::Util.html_escape(formatted_object)
         | 
| 311 | 
            +
            					end
         | 
| 272 312 | 
             
            				end
         | 
| 273 313 | 
             
            			end
         | 
| 274 314 |  | 
| 275 315 | 
             
            			nil
         | 
| 276 316 | 
             
            		end
         | 
| 277 317 |  | 
| 278 | 
            -
            		def _attributes(**attributes)
         | 
| 318 | 
            +
            		private def _attributes(**attributes)
         | 
| 279 319 | 
             
            			if attributes[:href]&.start_with?(/\s*javascript/)
         | 
| 280 320 | 
             
            				attributes[:href] = attributes[:href].sub(/^\s*(javascript:)+/, "")
         | 
| 281 321 | 
             
            			end
         | 
| @@ -290,7 +330,7 @@ module Phlex | |
| 290 330 | 
             
            			buffer
         | 
| 291 331 | 
             
            		end
         | 
| 292 332 |  | 
| 293 | 
            -
            		def _build_attributes(attributes, buffer:)
         | 
| 333 | 
            +
            		private def _build_attributes(attributes, buffer:)
         | 
| 294 334 | 
             
            			attributes.each do |k, v|
         | 
| 295 335 | 
             
            				next unless v
         | 
| 296 336 |  | 
| @@ -309,13 +349,13 @@ module Phlex | |
| 309 349 | 
             
            				when true
         | 
| 310 350 | 
             
            					buffer << " " << name
         | 
| 311 351 | 
             
            				when String
         | 
| 312 | 
            -
            					buffer << " " << name << '="' <<  | 
| 352 | 
            +
            					buffer << " " << name << '="' << ERB::Util.html_escape(v) << '"'
         | 
| 313 353 | 
             
            				when Symbol
         | 
| 314 | 
            -
            					buffer << " " << name << '="' <<  | 
| 354 | 
            +
            					buffer << " " << name << '="' << ERB::Util.html_escape(v.name) << '"'
         | 
| 315 355 | 
             
            				when Hash
         | 
| 316 356 | 
             
            					_build_attributes(v.transform_keys { "#{k}-#{_1.name.tr('_', '-')}" }, buffer: buffer)
         | 
| 317 357 | 
             
            				else
         | 
| 318 | 
            -
            					buffer << " " << name << '="' <<  | 
| 358 | 
            +
            					buffer << " " << name << '="' << ERB::Util.html_escape(v.to_s) << '"'
         | 
| 319 359 | 
             
            				end
         | 
| 320 360 | 
             
            			end
         | 
| 321 361 |  | 
    
        data/lib/phlex/table.rb
    CHANGED
    
    | @@ -50,13 +50,11 @@ module Phlex | |
| 50 50 | 
             
            			child.alias_method :foot_cell, :cell
         | 
| 51 51 | 
             
            		end
         | 
| 52 52 |  | 
| 53 | 
            -
            		private
         | 
| 54 | 
            -
             | 
| 55 | 
            -
            		def properties
         | 
| 53 | 
            +
            		private def properties
         | 
| 56 54 | 
             
            			self.class.properties
         | 
| 57 55 | 
             
            		end
         | 
| 58 56 |  | 
| 59 | 
            -
            		def collection_template(&block)
         | 
| 57 | 
            +
            		private def collection_template(&block)
         | 
| 60 58 | 
             
            			table do
         | 
| 61 59 | 
             
            				head_template
         | 
| 62 60 | 
             
            				body_template(&block)
         | 
| @@ -64,11 +62,11 @@ module Phlex | |
| 64 62 | 
             
            			end
         | 
| 65 63 | 
             
            		end
         | 
| 66 64 |  | 
| 67 | 
            -
            		def item_template
         | 
| 65 | 
            +
            		private def item_template
         | 
| 68 66 | 
             
            			row_template
         | 
| 69 67 | 
             
            		end
         | 
| 70 68 |  | 
| 71 | 
            -
            		def head_template
         | 
| 69 | 
            +
            		private def head_template
         | 
| 72 70 | 
             
            			if self.class.properties.any? { |p| p[:header] }
         | 
| 73 71 | 
             
            				head do
         | 
| 74 72 | 
             
            					head_row do
         | 
| @@ -85,14 +83,14 @@ module Phlex | |
| 85 83 | 
             
            			end
         | 
| 86 84 | 
             
            		end
         | 
| 87 85 |  | 
| 88 | 
            -
            		def body_template
         | 
| 86 | 
            +
            		private def body_template
         | 
| 89 87 | 
             
            			body { yield_items }
         | 
| 90 88 | 
             
            		end
         | 
| 91 89 |  | 
| 92 | 
            -
            		def foot_template
         | 
| 90 | 
            +
            		private def foot_template
         | 
| 93 91 | 
             
            		end
         | 
| 94 92 |  | 
| 95 | 
            -
            		def row_template
         | 
| 93 | 
            +
            		private def row_template
         | 
| 96 94 | 
             
            			body_row do
         | 
| 97 95 | 
             
            				self.class.properties.each do |property|
         | 
| 98 96 | 
             
            					body_cell(**property[:attributes]) do
         | 
    
        data/lib/phlex/version.rb
    CHANGED
    
    
    
        data/lib/phlex.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: phlex
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.0.0 | 
| 4 | 
            +
              version: 1.0.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Joel Drapper
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2022- | 
| 11 | 
            +
            date: 2022-12-08 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: zeitwerk
         | 
| @@ -81,9 +81,9 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 81 81 | 
             
                  version: '2.7'
         | 
| 82 82 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 83 83 | 
             
              requirements:
         | 
| 84 | 
            -
              - - " | 
| 84 | 
            +
              - - ">="
         | 
| 85 85 | 
             
                - !ruby/object:Gem::Version
         | 
| 86 | 
            -
                  version:  | 
| 86 | 
            +
                  version: '0'
         | 
| 87 87 | 
             
            requirements: []
         | 
| 88 88 | 
             
            rubygems_version: 3.3.25
         | 
| 89 89 | 
             
            signing_key:
         |