代码之家  ›  专栏  ›  技术社区  ›  user181548

如何处理模板工具包中的模板依赖项?

  •  5
  • user181548  · 技术社区  · 15 年前

    我的静态网页是由大量的模板构建的,这些模板使用Template Toolkit的“import”和“include”相互包含,因此page.html如下所示:

    [% INCLUDE top %]
    [% IMPORT middle %]
    

    然后top可能包含更多的文件。

    我有很多这样的文件,它们必须运行,才能创建各种语言(英语、法语等,而不是计算机语言)的网页。这是一个非常复杂的过程,当一个文件被更新时,我希望能够使用makefile或类似的东西自动重新生成所需的文件。

    有什么工具像 makedepend 对于可以解析模板工具包模板并创建依赖项列表以在生成文件中使用的C文件?

    或者有更好的方法使这个过程自动化吗?

    3 回复  |  直到 15 年前
        1
  •  3
  •   draegtun    15 年前

    Template Toolkit 带有自己的命令行脚本 ttree 用于建立TT网站。

    这里是一个 ttree.cfg 我经常在Mac电脑上的TT网站项目中使用的文件:

    # directories
    src = ./src
    lib = ./lib
    lib = ./content
    dest = ./html
    
    # pre process these site file
    pre_process = site.tt
    
    # copy these files
    copy = \.(png|gif|jpg)$
    
    # ignore following
    ignore = \b(CVS|RCS)\b
    ignore = ^#
    ignore = ^\.DS_Store$
    ignore = ^._
    
    # other options
    verbose
    recurse
    

    只是跑 ttree -f ttree.cfg 将在中重建网站 dest 仅在源位置更新已更改的内容(在 src )或者在我的库中(在 lib )

    对于更细粒度的依赖项,请查看 Template Dependencies .

    更新 -下面是我通过子类化获取依赖列表的技巧 Template::Provider :

    {
        package MyProvider;
        use base 'Template::Provider';
    
        # see _dump_cache in Template::Provider
        sub _dump_deps {
            my $self = shift;
    
            if (my $node = $self->{ HEAD }) {
                while ($node) {
                    my ($prev, $name, $data, $load, $next) = @$node;
    
                    say {*STDERR} "$name called from " . $data->{caller}
                        if exists $data->{caller};
    
                    $node = $node->[ 4 ];
                }
            }
        }
    }
    
    
    use Template;
    
    my $provider = MyProvider->new;
    
    my $tt = Template->new({
        LOAD_TEMPLATES => $provider,
    });
    
    $tt->process( 'root.tt', {} ) or die $tt->error;
    
    $provider->_dump_deps;
    

    上面的代码显示了调用的所有依赖项(通过include、insert、process和wrapper),以及从整个 root.tt 树。所以你可以通过这个 T树 依赖关系文件。

    /I3AZ/

        2
  •  1
  •   Sinan Ünür    15 年前

    如果您只关心查找指令中提到的文件名,例如 INCLUDE , PROCESS , WRAPPER 等等,有人甚至想象 sed perl 从命令行生成依赖项。

    但是,如果存在更细微的依赖关系(例如,使用 <img> 在HTML文档中,其大小是使用 Image plugin ,问题会变得不那么容易处理。

    我还没有真正测试过,但可能会有如下效果:

    #!/usr/bin/perl
    
    use strict; use warnings;
    
    use File::Find;
    use File::Slurp;
    use Regex::PreSuf;
    
    my ($top) = @ARGV;
    
    my $directive_re = presuf qw( INCLUDE IMPORT PROCESS );
    
    my $re = qr{
        \[%-? \s+ $directive_re \s+ (\S.+) \s+ -?%\]
    }x;
    
    find(\&wanted => $top);
    
    sub wanted {
        return unless /\.html\z/i;
    
        my $doc = read_file $File::Find::name;
        printf "%s : %s\n", $_, join(" \\\n", $doc =~ /$re/g );
    }
    
        3
  •  0
  •   user181548    15 年前

    在阅读完ttree文档之后,我决定自己创建一些东西。我把它贴在这里,以防对下一个来的人有用。然而,这并不是一个普遍的解决方案,而是一个只适用于少数有限情况的解决方案。它适用于此项目,因为所有文件都在同一目录中,并且没有重复的include。我在每一个例程之前都将这些缺陷记录为注释。

    如果有一个简单的方法来处理我错过的ttree,请告诉我。

    my @dependencies = make_depend ("first_file.html.tmpl");
    
    # Bugs:
    # Insists files end with .tmpl (mine all do)
    # Does not check the final list for duplicates.
    
    sub make_depend
    {
        my ($start_file) = @_;
        die unless $start_file && $start_file =~ /\.tmpl/ && -f $start_file;
        my $dir = $start_file;
        $dir =~ s:/[^/]*$::;
        $start_file =~ s:\Q$dir/::;
        my @found_files;
        find_files ([$start_file], \@found_files, $dir);
        return @found_files;
    }
    
    # Bugs:
    # Doesn't check for including the same file twice.
    # Doesn't allow for a list of directories or subdirectories to find the files.
    # Warning about files which aren't found switched off, due to
    # [% INCLUDE $file %]
    
    sub find_files
    {
        my ($files_ref, $foundfiles_ref, $dir) = @_;
        for my $file (@$files_ref) {
            my $full_name = "$dir/$file";
            if (-f $full_name) {
                push @$foundfiles_ref, $full_name;
                my @includes = get_includes ($full_name);
                if (@includes) {
                    find_files (\@includes, $foundfiles_ref, $dir);
                }
            } else {
    #            warn "$full_name not found";
            }
        }
    }
    
    # Only recognizes two includes, [% INCLUDE abc.tmpl %] and [% INCLUDE "abc.tmpl" %]
    
    sub get_includes
    {
        my ($start_file) = @_;
        my @includes;
        open my $input, "<", $start_file or die "Can't open $start_file: $!";
        while (<$input>) {
            while (/\[\%-?\s+INCLUDE\s+(?:"([^"]+)"|(.*))\s+-?\%\]/g) {
                my $filename = $1 ? $1 : $2;
                push @includes, $filename;
            }
        }
        close $input or die $!;
        return @includes;
    }