2010-03-23 24 views
5

Mis páginas web estáticas se construyen a partir de un gran ramo de plantillas que son inter-incluido el uso de "importación" de la plantilla y el kit de herramientas de "incluir", por lo pagina.html se parece a esto:¿Cómo puedo manejar las dependencias de plantilla en Template Toolkit?

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

A continuación, la parte superior puede tener incluso más archivos incluidos.

Tengo muchos de estos archivos, y se deben ejecutar para crear las páginas web en varios idiomas (inglés, francés, etc., no en idiomas de computadora). Este es un proceso muy complicado y cuando se actualiza un archivo, me gustaría poder rehacer automáticamente solo los archivos necesarios, usando un archivo MAKE o algo similar.

¿Hay herramientas como makedepend para archivos C que pueden analizar plantillas de plantillas de herramientas y crear una lista de dependencias para su uso en un archivo MAKE?

¿O existen mejores formas de automatizar este proceso?

Respuesta

3

Template Toolkit viene con su propio script de línea de comandos llamado ttree para crear sitios web de TT ala make.

Aquí es un archivo ttree.cfg A menudo utilizo uso en proyectos de sitios web TT aquí en mi 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 

Sólo corriendo ttree -f ttree.cfg va a reconstruir el sitio en dest única actualización de lo que ha sido cambiado en la fuente (en src) o en mis bibliotecas (en lib).

Para obtener más dependencias de grano fino, eche un vistazo a Template Dependencies.

actualización - Y aquí está mi puñalada en la lista de dependencias conseguir subclasificando 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; 

El código anterior muestra todas las dependencias llamados (a través de INCLUDE, INSERT, PROCESO y la envoltura) y donde llaman desde dentro todo el árbol root.tt. Entonces a partir de esto podría compilar un archivo de dependencia ttree.

/I3az/

+0

Encuentro 'dependen' en' .ttreerc' un poco escamoso e inconveniente con largas listas de dependencias. Debería buscar en 'ttree' para ver cómo están lidiando con eso. –

+0

@Aaahh, usa 'Text :: ParseWords' para analizar las dependencias. Ahora, eso explica mucho ;-) En cualquier caso, creo que el OP quiere saber si puede generar esa información de dependencia automáticamente basándose en las directivas '[% - INCLUDE -%]' etc. en los archivos de plantilla. Sin embargo, +1 para señalar '.ttreerc'. –

+0

@Sinan: tenía un 2-3 ideas sobre el bit de la dependencia, pero me sentí mejor dejándolo así hasta que tuviera algo concreto. Ver mi actualización – draegtun

1

En caso de que todo lo que importa son la búsqueda de nombres de archivos mencionados en las directivas tales como INCLUDE, PROCESS, WRAPPER etc, uno imaginar incluso utilizando sed o perl desde la línea de comandos para generar las dependencias.

Sin embargo, si hay dependencias sutiles (por ejemplo, se hace referencia a una imagen utilizando <img> en su documento HTML cuyo tamaño se calcula utilizando la Image plugin, el problema puede llegar a ser mucho menos manejable.

Realmente no he probado pero algo como lo siguiente podría funcionar:

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

Hay muchas dependencias como la '' que mencionas, pero me gustaría al menos comenzar por sacarlas del archivo. Sigo perdiendo dependencias de mi archivo MAKE, y luego las compilaciones no reflejan los cambios cuando se editan las plantillas. –

0

Después de leer la documentación ttree, decidí crear algo yo he publicado aquí en caso de que sea útil a la siguiente persona que viene a lo largo sin embargo, esta.. no es una solución general, sino que funciona solo para unos pocos casos limitadosFuncionó para este proyecto ya que todos los archivos están en el mismo directorio y no hay duplicados. Documenté las deficiencias como comentarios antes de cada una de las rutinas.

Si hay una manera simple de hacer lo que hace con ttree que me perdí, házmelo saber.

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; 
} 
Cuestiones relacionadas