Template-LiquidX-Tidy

 view release on metacpan or  search on metacpan

lib/Template/LiquidX/Tidy/impl.pm  view on Meta::CPAN

package Template::LiquidX::Tidy::impl;

use strict;
use warnings;
use experimental 'signatures';

our $VERSION = '0.03';

use Exporter 'import';
our @EXPORT_OK = qw(_tidy_list _tidy_make_string);
use vars '%defaults';
*defaults = \%Template::LiquidX::Tidy::defaults;

# parser regex
our $PI_START = qr/\{%-?/;
our $PI_END = qr/-?%\}/;
our $LV_START = qr/\{\{/;

# pseudo html indenter
# $html - fragment of html to chunk into lines
# $args - indenter configuration
# $level - current level
# $clevel - current level for debugging
# $stack - additional storage for
#           open_tags /
#           closed_tags /
#           level at return time
# returns a list of [ level, fragment ] pairs and modifies $stack
sub _tidy_html ($html, $args, $level, $clevel, $stack) {
    #print ((" " x $clevel ). "_tidy_html <<$html>> <<$level>>\n");
    my $nl = $html =~ /\n/;
    my @return;
    my $last_line_start = 0;
    my $start_level = $level;
    my $level_change = '';
    while ($html =~ m{(?: (?<cdata> <!\[CDATA\[(.*?)\]\]> )
		        | (?<nl> \n )
			| (?<close2> />)
		        | <(?<close> /)? (?<tag> \w+ )
			) }gsx) {
	#use Data::Dumper; warn Dumper \%+;
	if ($+{cdata}) {
	    # ignore
	}
	elsif (length $+{nl}) {
	    1 while $level_change =~ s/\(\)//;
	    push @return, [ $start_level - ($level_change =~ y/)//), (substr $html, $last_line_start, (pos $html) - $last_line_start),
			    +{ html => 1,
			       ($stack->{open_tags} ? (open => [$stack->{open_tags}->@*]) : ()),
			       ($stack->{closed_tags} ? (closed => [$stack->{closed_tags}->@*]) : ()), } ];
	    $last_line_start = pos($html);
	    $start_level = $level;
	    $level_change = '';
	}
	else {
	    my $tag = $+{tag} ? lc $+{tag} : '';
	    if ($tag =~ /^(?| area | base | br | col | embed | hr | img | input | link | meta | source | track | wbr )$/ix) {
		push $stack->{waiting}->@*, $tag;
	    }
	    elsif ($+{close2}) {
		if ($stack->{waiting} && $stack->{waiting}->@*) {
		    pop $stack->{waiting}->@*;
		} else {
		    pop $stack->{open_tags}->@*;
		    $level_change .= ')';
		    $level--;
		    #print ((" " x $clevel ). " close2 <<$level_change>> <<$start_level>>\n");
		}
	    }
	    elsif ($+{close}) {
		if ($stack->{waiting} && $stack->{waiting}->@* && $stack->{waiting}[-1] eq $tag) {
		    pop $stack->{waiting}->@*;
		}
		else {
		    if ($stack->{open_tags} && $stack->{open_tags}[-1] eq $tag) {
			pop $stack->{open_tags}->@*;
		    } else {
			push $stack->{closed_tags}->@*, $tag;
		    }
		    $level_change .= ')';
		    $level--;
		    $stack->{waiting}->@* = ();
		    #print ((" " x $clevel ). " close<<$tag>> <<$level_change>> <<$start_level>>\n");
		}
	    }
	    else {
		push $stack->{open_tags}->@*, $tag;
		$level_change .= '(';
		$level++;
		$stack->{waiting}->@* = ();
		#print ((" " x $clevel ). " open<<$tag>> <<$level_change>> <<$start_level>>\n");
	    }
	}
    }
    if ($last_line_start < length $html) {
	1 while $level_change =~ s/\(\)//;
	push @return, [ $start_level - ($level_change =~ y/)//), (substr $html, $last_line_start),
			+{ html => 1,
			   ($stack->{open_tags} ? (open => [$stack->{open_tags}->@*]) : ()),
			   ($stack->{closed_tags} ? (closed => [$stack->{closed_tags}->@*]) : ()), } ];
    }
    $stack->{level} = $level;



( run in 0.550 second using v1.01-cache-2.11-cpan-13bb782fe5a )