Author: amc
Date: Thu Nov 10 21:02:20 2011
New Revision: 1200544

URL: http://svn.apache.org/viewvc?rev=1200544&view=rev
Log:
Side tree nav, attempt 1.

Modified:
    trafficserver/site/branches/ats-cms/lib/view.pm
    trafficserver/site/branches/ats-cms/templates/docs_page.html

Modified: trafficserver/site/branches/ats-cms/lib/view.pm
URL: 
http://svn.apache.org/viewvc/trafficserver/site/branches/ats-cms/lib/view.pm?rev=1200544&r1=1200543&r2=1200544&view=diff
==============================================================================
--- trafficserver/site/branches/ats-cms/lib/view.pm (original)
+++ trafficserver/site/branches/ats-cms/lib/view.pm Thu Nov 10 21:02:20 2011
@@ -39,14 +39,25 @@ sub _SplitContentName {
     return @zret;
 }
 
+# This is basically File::Spec::catdir except it makes a relative path
+# of just 'dir' if the base path is empty.
+sub _append_to_path {
+    my ($path, $dir) = @_;
+    return $path ? File::Spec->catdir($path, $dir) : $dir;
+}
+
 package view::Source;
 # A source / content file. This is a terminal in the documentation tree.
 # It has a map of language tags -> original file.
 
-# _LANGMAP -> Hash from language tag to source file.
+# _LANGMAP -> Hash from language tag to source file data.
+#   _FILE -> Local file name.
+#   _LINK -> File name for HTML links.
+#   _VARS -> Internal file variables.
+#  
 # _STEM -> The stem for this source.
 # _PATH -> Path of the directory containing this source.
-# _VARS -> Template variables to be used during generation.
+# _VARS -> External variables for stem.
 
 sub new {
     my ($self, $path, $stem) = @_;
@@ -69,6 +80,7 @@ sub stem { return $_[0]->{_STEM}; }
 sub path { return $_[0]->{_PATH}; }
 # This is a convenience so we don't have to check for being a node.
 sub srcCount { return 0; }
+sub isTop { return 0; }
 
 sub parent {
     my ($self) = @_;
@@ -90,37 +102,49 @@ sub vars {
     return $zret;
 }
 
-sub setVars {
-    my ($self, $vars) = @_;
-    $self->{_VARS}{keys %$vars} = values %$vars;
-    return $self;
+sub setFileForLang {
+    my ($self, $file, $lang) = @_;
+    my $link = join('.', (view::_SplitContentName($file))[0,1], 'html');
+    $self->{_LANGMAP}{$lang} = {
+        _FILE => $file,
+        _LINK => $link
+    };
+}
+
+# Access the language specific data
+sub langToData {
+    my ($self, $lang) = @_;
+    my $zret = $self->{_LANGMAP}{$lang} || 
$self->{_LANGMAP}{view::DEFAULT_LANG()};
+    die "Stem '", $self->stem, "' in '", $self->{_PATH}, "' does not have 
language '$lang' or the default '", view::DEFAULT_LANG(), "'.\n" unless $zret;
+    # Fault in the file at this point.
+    if (not $zret->{_VARS}) {
+        my %vars = %{$self->vars}; # copy external variables over.
+        my $var_path = File::Spec->catfile($self->path, $zret->{_FILE});
+        view::read_text_file $var_path, \%vars; # add file internal vars.
+        $zret->{_VARS} = \%vars;
+    }
+    return $zret;
 }
 
 # Get/Set the file for lang. This should be the local file name, not a path.
 sub langToFile {
     my ($self, $lang, $file) = @_;
-    my $zret = $self->{_LANGMAP}{$lang};
-    if (scalar @_ > 2) {
-        $self->{_LANGMAP}{$lang} = $file;
-    } else {
-        $zret = $self->{_LANGMAP}{view::DEFAULT_LANG()} unless $zret;
-        die "Stem '", $self->stem, "' in '", $self->{_PATH}, "' does not have 
language '$lang' or the default '", view::DEFAULT_LANG(), "'.\n" unless $zret;
-    }
-    return $zret;
+    return $self->langToData($lang)->{_FILE};
 }
 
-# Set the link name for @a lang.
+# Get the link name for @a lang.
 sub langToLink {
     my ($self, $lang) = @_;
-    my $file = $self->langToFile($lang);
-    if ($file) {
-        my $stem = (view::_SplitContentName($file))[0];
-        $file = "$stem.$lang.html";
-    }
-    return $file;
+    return $self->langToData($lang)->{_LINK};
+}
+
+# Get the variables (including content) for a language.
+sub langToVars {
+    return $_[0]->langToData($_[1])->{_VARS};
 }
 
-# Just set the lang tag map from another instance.
+# Set the lang map / data directly.
+# Used by stem loading logic.
 sub copyLangMap {
     my ($self, $that) = @_;
     $self->{_LANGMAP} = $that->{_LANGMAP};
@@ -132,12 +156,37 @@ sub langList {
     return keys %{$self->{_LANGMAP}};
 }
 
+# Compute a relative path from this source to another.
+sub pathTo {
+    my ($self, $dest) = @_;
+    my @spath = File::Spec->splitdir($self->path);
+    my @dpath = File::Spec->splitdir($dest->path);
+    my $rpath = '';
+
+    # strip off matching ancestors from the top.    
+    while (scalar @spath and scalar @dpath and $spath[0] eq $dpath[0]) {
+        shift @spath;
+        shift @dpath;
+    }
+    # Now work up the source path.
+    while (scalar @spath) {
+        $rpath = view::_append_to_path($rpath, '..');
+        pop @spath;
+    }
+    # Then back down the destination.
+    while (scalar @dpath) {
+        $rpath = view::_append_to_path($rpath, shift @dpath);
+    }
+    return $rpath;
+}
+
 package view::Node;
 our @ISA = ( 'view::Source' );
 # Boolean constants
 use constant TRUE => 1;
 use constant FALSE => 0;
 use Carp;
+use Clone;
 
 # Map from directory paths to Nodes.
 our %Locations;
@@ -167,11 +216,12 @@ sub isTop {
     return $zret;
 }
 
-# Because File::Spec::updir just add a '..' to the end.
+# Because File::Spec::updir just adds a '..' to the end.
 sub ParentDir {
     my ($path) = @_;
     my @d = File::Spec->splitdir($path);
     my $p;
+    # Bizarre but it handles emtpy directories.
     do {
         $p = pop @d;
     } while scalar @d and not $p;
@@ -253,7 +303,7 @@ sub _LoadStems{
                 } elsif (not ref $src) {
                     die "Stem '$stem' used for both files and directory in 
'$dir'.\n";
                 }
-                $src->langToFile($lang, $name);
+                $src->setFileForLang($name, $lang);
             }
         }
     }
@@ -336,10 +386,11 @@ sub GetLocation {
         $node = _LoadPath($dir);
         $Locations{$dir} = $node;
         if (not $node->isTop) {
-            my $parent = $node->parent;
+            my $parent = $node->parent; # magic recursion happens here.
             my %locals = %{$node->vars}; # cache local vars.
-            %{$node->vars} = %{$parent->vars}; # set all parent values.
-            $node->vars->{keys %locals} = values %locals;
+            $node->vars(Clone::clone($parent->vars)); # copy parent values.
+            # overwrite parent values with locals.
+            @{$node->vars->{keys %locals}} = values %locals;
         }
     }
     return $node;
@@ -407,8 +458,9 @@ sub single_narrative {
     my ($src, $lang) = view::Node::GetSource($file);
     $args{langs} = langs($src, $lang);
     $args{lang} = $lang;
-    $args{keys %{$src->vars}} = values %{$src->vars}; # override with source 
variables.
-    read_text_file $file, \%args;
+    # copy over file local vars, including content.
+    my $fvars = $src->langToVars($lang);
+    @args{keys %$fvars} = values %$fvars;
     nav_links($src, \%args) if $args{headers}{navigation};
     
     return Dotiac::DTL::Template($template)->render(\%args), html => \%args;
@@ -539,11 +591,37 @@ sub breadcrumbs {
 
 # --------------
 
-# This is basically File::Spec::catdir except it forces an absolute path if
-# the current path is empty.
-sub append_to_path {
-    my ($path, $dir) = @_;
-    return $path ? File::Spec->catdir($path, $dir) : $dir;
+# Generate a navigation subtree starting at this node.
+# Also need the language and relative path.
+sub nav_sub_tree {
+    my ($src, $target, $lang) = @_;
+    my $text = '<li>';
+    my $rpath = $src->pathTo($target);
+    
+    $text .= '<a href="';
+    $text .= _append_to_path($rpath, $target->langToLink($lang));
+    $text .= '" >';
+    $text .= $target->langToVars($lang)->{headers}{title} || '<strong>Title 
Missing</strong>';
+    $text .= '</a>';
+    
+    my $n = $target->srcCount;
+    if ($n) {
+        $text .= '<ul>';
+        for (my $i = 0 ; $i < $n ; ++$i) {
+            $text .= nav_sub_tree($src, $target->srcAt($i), $lang);
+        }
+        $text .= '</ul>';
+    }
+    
+    $text .= '</li>';
+    return $text;
+}
+
+# Compute the full tree containing this node.
+sub nav_full_tree {
+    my ($node, $lang) = @_;
+    my $top = $node->top;
+    return '<ul>' . nav_sub_tree($node, $top, $lang) . '</ul>';
 }
 
 # Args:
@@ -555,8 +633,8 @@ sub next_link {
     my ($node, $idx, $lang, $rpath) = @_;
     my $other = $node->srcAt($idx);
     my $url = '';
-    $url = append_to_path($rpath, $other->stem) if $other->isa('view::Node');
-    $url = append_to_path($url, $other->langToLink($lang));
+    $url = _append_to_path($rpath, $other->stem) if $other->isa('view::Node');
+    $url = _append_to_path($url, $other->langToLink($lang));
     return $url;    
 }
 
@@ -571,11 +649,11 @@ sub right_leaf {
     while (1) {
         if ($src->srcCount > 0) {
             # src is a directory with multiple nodes, descend in to it.
-            $rpath = append_to_path($rpath, $src->stem);
+            $rpath = _append_to_path($rpath, $src->stem);
             $node = $src;
             $src = $node->srcAt($node->srcCount - 1);
         } else { # we've hit the bottom, finish.
-            $rpath = append_to_path($rpath, $stem) if $src->isa('view::Node');
+            $rpath = _append_to_path($rpath, $stem) if $src->isa('view::Node');
             $rpath = $rpath ? File::Spec->catfile($rpath, 
$src->langToLink($lang)) : $src->langToLink($lang);
             last;
         }
@@ -602,7 +680,7 @@ sub auto_nav {
         my $bpath = $src->isa('view::Node') ? '..' : '';
         my $idx = $parent->indexOfStem($src->stem);
         if (0 == $idx) { # back from first stem is parent content
-            $back_url = append_to_path($bpath, $parent->langToLink($lang));
+            $back_url = _append_to_path($bpath, $parent->langToLink($lang));
         } else {
             $back_url = right_leaf($parent, $parent->srcAt($idx-1)->stem, 
$lang, $bpath);
         }
@@ -626,11 +704,10 @@ sub auto_nav {
             my $n = $parent->srcCount;
             if ($idx < $n - 1 ) {
                 $next_url = next_link($parent, $idx+1, $lang, $rpath);
-            } else {
-                $rpath = append_to_path($rpath, '..');
             }
         }
         last if $parent->isTop;
+        $rpath = _append_to_path($rpath, '..');
         $src = $parent;
         $parent = $src->parent;
     }
@@ -712,6 +789,8 @@ sub nav_links {
         my $auto_navs = auto_nav($src, $lang);
         $args->{nav} = $auto_navs if @$auto_navs;
     }
+    
+    $args->{nav_tree} = nav_full_tree($src, $lang);
 }
 
 # Arg: Target file path.

Modified: trafficserver/site/branches/ats-cms/templates/docs_page.html
URL: 
http://svn.apache.org/viewvc/trafficserver/site/branches/ats-cms/templates/docs_page.html?rev=1200544&r1=1200543&r2=1200544&view=diff
==============================================================================
--- trafficserver/site/branches/ats-cms/templates/docs_page.html (original)
+++ trafficserver/site/branches/ats-cms/templates/docs_page.html Thu Nov 10 
21:02:20 2011
@@ -79,6 +79,7 @@
       </div>
       <div class="fourcol last">
         {{ global_nav|markdown }}
+        {% if nav_tree %}{{ nav_tree|safe }}{% endif %}
       </div>
     </div>
 


Reply via email to