如何处理 Template Toolkit 中的模板依赖关系?

发布于 2024-08-26 00:47:44 字数 471 浏览 6 评论 0原文

我的静态网页是由大量模板构建的,这些模板使用 Template Toolkit 的“导入”和“包含”相互包含,因此 page.html 看起来像这样:

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

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

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

是否有像 makedepend 这样的 C 文件工具可以解析模板工具包模板并创建在 makefile 中使用的依赖项列表?

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

My static web pages are built from a huge bunch of templates which are inter-included using Template Toolkit's "import" and "include", so page.html looks like this:

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

Then top might have even more files included.

I have very many of these files, and they have to be run through to create the web pages in various languages (English, French, etc., not computer languages). This is a very complicated process and when one file is updated I would like to be able to automatically remake only the necessary files, using a makefile or something similar.

Are there any tools like makedepend for C files which can parse template toolkit templates and create a dependency list for use in a makefile?

Or are there better ways to automate this process?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

妄断弥空 2024-09-02 00:47:44

Template Toolkit 确实附带了自己的命令行脚本,称为 ttree 用于构建 TT 网站。

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

# 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::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 树。因此,您可以从此构建一个 ttree 依赖文件。

/I3az/

Template Toolkit does come with its own command line script called ttree for building TT websites ala make.

Here is an ttree.cfg file I use often use on TT website projects here on my Mac:

# 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

Just running ttree -f ttree.cfg will rebuild the site in dest only updating whats been changed at source (in src) or in my libraries (in lib).

For more fine grained dependencies have a look a Template Dependencies.

Update - And here is my stab at getting dependency list by subclassing 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;

The code above displays all dependencies called (via INCLUDE, INSERT, PROCESS and WRAPPER) and where called from within the whole root.tt tree. So from this you could build a ttree dependency file.

/I3az/

迷离° 2024-09-02 00:47:44

如果您关心的只是查找 INCLUDEPROCESSWRAPPER 等指令中提到的文件名,甚至可以想象使用 从命令行使用 sedperl 来生成依赖项。

但是,如果存在更微妙的依赖性(例如,您在 HTML 文档中使用 引用图像,其大小是使用 图像插件,问题可能会变得更不容易处理。

我还没有真正测试过它,但类似下面的东西可能会起作用:

#!/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 );
}

In case all you care about are finding file names mentioned in directives such as INCLUDE, PROCESS, WRAPPER etc, one imagine even using sed or perl from the command line to generate the dependencies.

However, if there are subtler dependencies (e.g., you reference an image using <img> in your HTML document whose size is calculated using the Image plugin, the problem can become much less tractable.

I haven't really tested it but something like the following might work:

#!/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 );
}
可爱咩 2024-09-02 00:47:44

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

如果有一个简单的方法可以对我错过的 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;
}

After reading the ttree documentation, I decided to create something myself. I'm posting it here in case it's useful to the next person who comes along. However, this is not a general solution, but one which works only for a few limited cases. It worked for this project since all the files are in the same directory and there are no duplicate includes. I've documented the deficiencies as comments before each of the routines.

If there is a simple way to do what this does with ttree which I missed, please let me know.

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文