diff --git a/lib/phlex/context.rb b/lib/phlex/context.rb index b2b27f55..231eb00b 100644 --- a/lib/phlex/context.rb +++ b/lib/phlex/context.rb @@ -5,9 +5,12 @@ class Phlex::Context def initialize @buffer = +"" @capturing = false + @fragment = nil + @in_target_fragment = false + @found_target_fragment = false end - attr_accessor :buffer, :capturing + attr_accessor :buffer, :capturing, :fragment, :in_target_fragment, :found_target_fragment # Added for backwards compatibility with phlex-rails. We can remove this with 2.0 def target diff --git a/lib/phlex/elements.rb b/lib/phlex/elements.rb index 4b28eba1..68bd3c24 100644 --- a/lib/phlex/elements.rb +++ b/lib/phlex/elements.rb @@ -42,7 +42,26 @@ def register_element(method_name, tag: method_name.name.tr("_", "-"), deprecated def #{method_name}(**attributes, &block) #{deprecation} - buffer = @_context.buffer + + context = @_context + buffer = context.buffer + fragment = context.fragment + end_find = false + + if fragment + in_target_fragment = context.in_target_fragment + + if !in_target_fragment + if !context.found_target_fragment && attributes[:id] == fragment + context.in_target_fragment = true + context.found_target_fragment = true + end_find = true + else + yield if block + return nil + end + end + end if attributes.length > 0 # with attributes if block # with content block @@ -64,6 +83,9 @@ def #{method_name}(**attributes, &block) #{'flush' if tag == 'head'} + # I think we can actually throw from here. + context.in_target_fragment = false if end_find + nil end @@ -90,7 +112,21 @@ def register_void_element(method_name, tag: method_name.name.tr("_", "-"), depre def #{method_name}(**attributes) #{deprecation} - buffer = @_context.buffer + context = @_context + buffer = context.buffer + fragment = context.fragment + + if fragment + in_target_fragment = context.in_target_fragment + + if !in_target_fragment + if !context.found_target_fragment && attributes[:id] == fragment + context.found_target_fragment = true + else + return nil + end + end + end if attributes.length > 0 # with attributes buffer << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[respond_to?(:process_attributes) ? (attributes.hash + self.class.hash) : attributes.hash] || __attributes__(**attributes)) << ">" diff --git a/lib/phlex/html.rb b/lib/phlex/html.rb index c21b0c4d..c34a3991 100644 --- a/lib/phlex/html.rb +++ b/lib/phlex/html.rb @@ -29,7 +29,10 @@ def __unbuffered_class__ # Output an HTML doctype. def doctype - @_context.buffer << "" + context = @_context + return if context.fragment && !context.in_target_fragment + + context.buffer << "" nil end diff --git a/lib/phlex/sgml.rb b/lib/phlex/sgml.rb index 5fe77cc3..cc0a447e 100644 --- a/lib/phlex/sgml.rb +++ b/lib/phlex/sgml.rb @@ -95,18 +95,19 @@ def await(task) end # Renders the view and returns the buffer. The default buffer is a mutable String. - def call(buffer = +"", context: Phlex::Context.new, view_context: nil, parent: nil, &block) - __final_call__(buffer, context: context, view_context: view_context, parent: parent, &block).tap do + def call(buffer = +"", context: Phlex::Context.new, view_context: nil, parent: nil, fragment: nil, &block) + __final_call__(buffer, context: context, view_context: view_context, parent: parent, fragment: fragment, &block).tap do self.class.rendered_at_least_once! end end # @api private - def __final_call__(buffer = +"", context: Phlex::Context.new, view_context: nil, parent: nil, &block) + def __final_call__(buffer = +"", context: Phlex::Context.new, view_context: nil, parent: nil, fragment: nil, &block) @_buffer = buffer @_context = context @_view_context = view_context @_parent = parent + @_context.fragment = fragment if fragment block ||= @_content_block @@ -139,6 +140,9 @@ def __final_call__(buffer = +"", context: Phlex::Context.new, view_context: nil, # @return [nil] # @see #format_object def plain(content) + context = @_context + return if context.fragment && !context.in_target_fragment + unless __text__(content) raise ArgumentError, "You've passed an object to plain that is not handled by format_object. See https://rubydoc.info/gems/phlex/Phlex/SGML#format_object-instance_method for more information" end @@ -150,7 +154,10 @@ def plain(content) # @return [nil] # @yield If a block is given, it yields the block with no arguments. def whitespace(&block) - buffer = @_context.buffer + context = @_context + return if context.fragment && !context.in_target_fragment + + buffer = context.buffer buffer << " " @@ -165,7 +172,10 @@ def whitespace(&block) # Output an HTML comment. # @return [nil] def comment(&block) - buffer = @_context.buffer + context = @_context + return if context.fragment && !context.in_target_fragment + + buffer = context.buffer buffer << "