Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
Checking mergeability… Don't worry, you can still create the pull request.
  • 3 commits
  • 6 files changed
  • 0 commit comments
  • 1 contributor
View
9 bin/ddg_publisher
@@ -2,6 +2,15 @@
# PODNAME: ddg_publisher
# ABSTRACT: Generating static parts of DuckDuckGo
+=head1 SYNOPSIS
+
+ perl -Ilib bin/ddg_publisher ~/test_publish
+
+ # compressing html to one line without comments and unnecessary whitespaces
+ perl -Ilib bin/ddg_publisher --no_compression ~/test_publish
+
+=cut
+
use FindBin qw($Bin);
use lib "$Bin/../lib";
View
41 lib/DDG/App/Publisher.pm
@@ -1,29 +1,70 @@
package DDG::App::Publisher;
+# ABSTRACT: The application class
+
+=head1 SYNOPSIS
+
+=cut
use MooX;
use MooX::Options protect_argv => 0;
use Path::Class;
use DDG::Publisher;
+=attr no_compression
+
+If this is deactivated the compression will not used, which speeds up the
+things for development.
+
+=cut
+
option no_compression => (
is => 'ro',
predicate => 1,
);
+=attr dryrun
+
+If this option is activated the publisher will not generate any files and
+will just execute the code so that tokens and generatly sanity of the code
+can be checked. This option requires a filename to be given, so this is used
+for the dryrun of L<Locale::Simple>.
+
+=cut
+
option dryrun => (
format => 's',
is => 'ro',
predicate => 1,
);
+=attr site_only
+
+Use this option to only execute one specific file. You can use it several
+times. Give the classname of the site you want to execute with the
+B<DDG::Publisher::Site::> part. This option can be given several times.
+
+=cut
+
option site_only => (
format => 's',
is => 'ro',
predicate => 1,
);
+=method run
+
+This method gets executed for the run of the publisher
+
+=cut
+
sub run {
my ( $self ) = @_;
+
+ #
+ # Getting the target directory from $ENV{DDG_PUBLISHER_TARGETDIR}
+ # or from command line.
+ #
+
my $target = @ARGV
? shift @ARGV
: defined $ENV{DDG_PUBLISHER_TARGETDIR}
View
53 lib/DDG/Publisher.pm
@@ -9,6 +9,12 @@ use HTML::Packer;
use String::ProgressBar;
use JSON;
+=attr site_classes
+
+List of classes that should get executed on publishing.
+
+=cut
+
has site_classes => (
is => 'ro',
lazy => 1,
@@ -21,17 +27,35 @@ sub _build_site_classes {[qw(
Dontbubbleus
)]}
+=attr sites
+
+This attribute holds the objects of the site classes that should get build.
+
+=cut
+
has sites => (
is => 'ro',
lazy => 1,
builder => 1,
);
+=attr no_compression
+
+See L<DDG::App::Publisher/no_compression>.
+
+=cut
+
has no_compression => (
is => 'ro',
default => sub { 0 },
);
+=attr dryrun
+
+See L<DDG::App::Publisher/dryrun>.
+
+=cut
+
has dryrun => (
is => 'ro',
predicate => 1,
@@ -53,6 +77,12 @@ sub BUILD {
$self->sites;
}
+=method publish_to
+
+This method it called to publish the files to the given specific directory.
+
+=cut
+
sub publish_to {
my ( $self, $target ) = @_;
my $target_dir = dir($target)->absolute;
@@ -62,7 +92,17 @@ sub publish_to {
unless ($self->no_compression) {
$packer = HTML::Packer->init();
}
+
+ #
+ # For every site...
+ #
+
for my $site (@{$self->sites}) {
+
+ #
+ # For every dir in the site...
+ #
+
for my $dir (values %{$site->dirs}) {
print "\n".(ref $site).$dir->web_path."\n\n";
my @files = values %{$dir->fullpath_files};
@@ -79,6 +119,12 @@ sub publish_to {
$real_file->dir->mkpath unless -f $real_file->dir->absolute->stringify;
my $content = $_->content;
utf8::encode($content);
+
+ #
+ # If compression is requested, then the content of the files
+ # get compressed via HTML::Packer here.
+ #
+
if ($packer) {
$packer->minify(\$content,{
remove_comments => 0,
@@ -94,6 +140,13 @@ sub publish_to {
}
print "\n";
}
+
+ #
+ # Generate a datafile for the site, which can be used for deeper
+ # processing of the static files. (It's used by the internal code
+ # of DDG to generate, for example, the nginx config)
+ #
+
my $data_file = file($target_dir,$site->key.'.json')->absolute;
io($data_file)->print(encode_json($site->save_data));
};
View
56 lib/DDG/Publisher/DirRole.pm
@@ -1,4 +1,5 @@
package DDG::Publisher::DirRole;
+# ABSTRACT: The role for a directory in the publisher system
use MooX::Role;
use DDG::Publisher::File;
@@ -8,16 +9,34 @@ requires qw(
pages
);
+=attr key
+
+The key inside the site for this directory. Required for instantiation.
+
+=cut
+
has key => (
is => 'ro',
required => 1,
);
+=attr site
+
+Site object for this directory. Required for instantiation.
+
+=cut
+
has site => (
is => 'ro',
required => 1,
);
+=attr files
+
+Contains a hash of the files for this directory.
+
+=cut
+
has files => (
is => 'ro',
lazy => 1,
@@ -57,6 +76,13 @@ sub _build_files {
return \%files;
}
+=attr fullpath
+
+This hash also contains all files, but with the full path on the filesystem
+as key, so that collides can be detected.
+
+=cut
+
has fullpath_files => (
is => 'ro',
lazy => 1,
@@ -80,6 +106,14 @@ sub _build_fullpath_files {
return \%fullpath_files;
}
+=attr pages_coderefs
+
+This attribute contains all the coderefs for the pages that have to be
+generated for this specific directory. It uses L<pages> as builder. Normally
+you override L<pages> in your site class.
+
+=cut
+
has pages_coderefs => (
is => 'ro',
lazy => 1,
@@ -88,6 +122,15 @@ has pages_coderefs => (
sub pages {{}}
+=attr statics_coderefs
+
+This attribute contains all the coderefs for the static pages that have to be
+generated for this specific directory. It uses L<statics> as builder. Normally
+you override L<statics> in your site class. A static file is not generated for
+every language
+
+=cut
+
has statics_coderefs => (
is => 'ro',
lazy => 1,
@@ -96,6 +139,12 @@ has statics_coderefs => (
sub statics {{}}
+=attr web_path
+
+The path on the web for this directory.
+
+=cut
+
has web_path => (
is => 'ro',
lazy => 1,
@@ -104,6 +153,13 @@ has web_path => (
sub _build_web_path { my @path = shift->path; defined $path[1] ? $path[1] : $path[0] }
+=attr template_path
+
+This is the path inside the templates, used for the pages and statics of this
+directory.
+
+=cut
+
has template_path => (
is => 'ro',
lazy => 1,
View
89 lib/DDG/Publisher/File.pm
@@ -1,4 +1,5 @@
package DDG::Publisher::File;
+# ABSTRACT: A file inside the publisher
use MooX;
use Locale::Simple;
@@ -11,17 +12,35 @@ sub fullpath {
return $fullpath;
}
+=attr dir
+
+L<DDG::Publisher::DirRole> object of this file
+
+=cut
+
has dir => (
is => 'ro',
required => 1,
);
+=attr static
+
+This is a static file, so its not generated for every language, only one file.
+
+=cut
+
has static => (
is => 'ro',
lazy => 1,
default => sub { 0 },
);
+=attr file
+
+Filename inside the directory of the site.
+
+=cut
+
has file => (
is => 'ro',
required => 1,
@@ -36,16 +55,35 @@ sub _build_file {
: $self->filebase.'/'.$self->locale.'.html'
}
+=attr file
+
+Base path inside the site directory, must be given on construction.
+
+=cut
+
has filebase => (
is => 'ro',
required => 1,
);
+=attr locale
+
+Locale used for this specific file.
+
+=cut
+
has locale => (
is => 'ro',
required => 1,
);
+=attr code
+
+Additional code that needs to be executed for getting the variables for the
+template of this file.
+
+=cut
+
has code => (
is => 'ro',
required => 1,
@@ -58,6 +96,15 @@ sub url {
return $self->dir->path.$self->filebase;
}
+=attr file
+
+Template name used, normally by default this is not used, instead B<base.tx>
+template is loaded by default, and this one is using the template variable. If
+there is a variable B<no_base> set inside the resulting variables for this
+file, then this template name is used instead of B<base.tx>
+
+=cut
+
has template => (
is => 'ro',
lazy => 1,
@@ -72,6 +119,13 @@ sub _build_template {
return $template;
}
+=attr content
+
+The resulting (uncompressed) content of the file. Fetching this will
+automatically fire up the template engine to generate the content.
+
+=cut
+
has content => (
is => 'ro',
lazy => 1,
@@ -81,13 +135,31 @@ has content => (
sub _build_content {
my ( $self ) = @_;
- # setting localization
+ #
+ # setting locale for the localilzation (see L<Locale::Simple>)
+ #
l_dir(dist_dir($self->dir->site->locale_dist));
ltd($self->dir->site->locale_domain);
l_lang($self->locale);
+ #
+ # Activating the dryrun if requested.
+ #
l_dry($self->dir->site->publisher->dryrun) if $self->dir->site->publisher->has_dryrun;
+ #
+ # Variables for the template
+ #
+ # f = reference to the file itself
+ # d = reference to the directory of the file
+ # s = reference to the site of directory of the file
+ #
+ # locale_package_version = Version number of the locale package
+ # locales = the hash of the locales for this token domain
+ # maintemplate = name of the template (so that base.tx can use it)
+ # url = the final URL for this specific page
+ #
+
my %vars = (
f => $self,
d => $self->dir,
@@ -99,14 +171,28 @@ sub _build_content {
);
my $site_code = $self->dir->site->can('code');
+
my $dir_code = $self->dir->can('code');
+ #
+ # Execute code from L<DDG::Publisher::SiteRole/code> to get more variables
+ #
%vars = ( %vars, $site_code->($self,\%vars) ) if $site_code;
+ #
+ # Execute code from L<DDG::Publisher::DirRole/code> to get more variables
+ #
%vars = ( %vars, $dir_code->($self,\%vars) ) if $dir_code;
+ #
+ # Execute code from L<code> to get more variables
+ #
%vars = ( %vars, $self->code->($self,\%vars) );
+ # explicit getting out no_base for template decision later
my $no_base = defined $vars{no_base} && $vars{no_base};
+ #
+ # Gathering the save data for the data files generation
+ #
$self->dir->site->save_data->{locales} = $self->dir->site->locale_package->locales
unless defined $self->dir->site->save_data->{locales};
$self->dir->site->save_data->{$self->dir->path} = {}
@@ -122,6 +208,7 @@ sub _build_content {
no_base => $no_base,
};
+ # execute template, return rendered content.
return $self->dir->site->template_engine->render($no_base ? $self->template : 'base.tx',\%vars);
}
View
67 lib/DDG/Publisher/SiteRole.pm
@@ -1,4 +1,5 @@
package DDG::Publisher::SiteRole;
+# ABSTRACT: The role for a site in the publisher
use MooX::Role;
use Class::Load ':all';
@@ -16,35 +17,70 @@ requires qw(
locale_domain
);
+=attr publisher
+
+L<DDG::Publisher> object, must be given on construction.
+
+=cut
+
has publisher => (
is => 'ro',
required => 1,
);
+=attr key
+
+This is the key used for the directory and general identification of the site
+inside the publisher system.
+
+=cut
+
has key => (
is => 'ro',
required => 1,
);
+=attr hostname
+
+This is the hostname, which should get used for the final files, so far this
+option isn't used and has no effect. B<TODO>
+
+=cut
+
has hostname => (
is => 'ro',
builder => 'default_hostname',
lazy => 1,
);
+=attr dirs
+
+This attribute contains the objects of the L<DDG::Publisher::DirRole> objects
+of this site.
+
+=cut
+
has dirs => (
is => 'ro',
builder => 1,
lazy => 1,
);
+=attr default_locale
+
+Default locale to use on this site. Defaults to en_US and should never be
+changed on a site of DuckDuckGo, as many other parts of the system are also
+thinking that en_US is the default.
+
+=cut
+
has default_locale => (
is => 'ro',
builder => 1,
lazy => 1,
);
-sub _build_default_locale { 'en_US' }
+sub _build_default_locale { 'en_US' } # DON'T CHANGE
sub _build_dirs {
my ( $self ) = @_;
@@ -60,6 +96,13 @@ sub _build_dirs {
} $self->dirs_classes};
}
+=attr save_data
+
+This data is used in the end of the publishing process to generate the data
+file. It will be filled up on the process of executing all files of the site.
+
+=cut
+
has save_data => (
is => 'rw',
lazy => 1,
@@ -77,6 +120,12 @@ sub locales {
return (keys %{$self->locale_package->locales});
}
+=attr template_engine
+
+This function holds the L<Text::Xslate> engine for the specific site.
+
+=cut
+
has template_engine => (
is => 'ro',
lazy => 1,
@@ -87,7 +136,11 @@ sub _build_template_engine {
my ( $self ) = @_;
my $site_template_root = dir(dist_dir('DDG-Publisher'),'site',$self->key)->stringify;
my $core_template_root = dir(dist_dir('DDG-Publisher'),'core')->stringify;
- # not necessary, but after i added it, i stored it here
+ #
+ # This hash contains the translation functions, wrapped with the
+ # functionality required to make it work proper with utf8 in the context
+ # of Text::Xslate.
+ #
my %xslate_locale_functions;
for my $key (keys %{ Locale::Simple->coderef_hash }) {
$xslate_locale_functions{$key} = sub {
@@ -97,9 +150,19 @@ sub _build_template_engine {
};
}
return Text::Xslate->new(
+ #
+ # Include share/site/$key and share/core as template directories
+ #
path => [$site_template_root,$core_template_root],
function => {
+ #
+ # js() function to escape js
+ #
js => sub { return mark_raw(javascript_value_escape(join("",@_))) },
+ #
+ # r() function to mark some output as "clean", which means that
+ # it doesnt get HTML encoded by the Xslate generation system.
+ #
r => sub { return mark_raw(join("",@_)) },
%xslate_locale_functions,
find_template => sub {

No commit comments for this range

Something went wrong with that request. Please try again.