diff --git a/.gitignore b/.gitignore index 557e602..82f569e 100644 --- a/.gitignore +++ b/.gitignore @@ -78,4 +78,4 @@ app-start Makefile .cache-* .t - +.* \ No newline at end of file diff --git a/META6.json b/META6.json index 8c837b9..f951860 100644 --- a/META6.json +++ b/META6.json @@ -17,7 +17,8 @@ "Pod::Utilities:ver<0.0.1>", "URI:ver<0.2.2>", "File::Temp:ver<0.0.6>", - "Log::Timeline:ver<0.3>" + "Log::Timeline:ver<0.3>", + "JSON::Fast:ver<0.9.18>" ], "description": "Represents a piece of Perl 6 that is documented.", "license": "Artistic-2.0", @@ -25,8 +26,9 @@ "perl": "6.c", "provides": { "Perl6::Documentable": "lib/Perl6/Documentable.pm6", - "Perl6::Documentable::File": "lib/Perl6/Documentable/File.pm6", - "Perl6::Documentable::Derived": "lib/Perl6/Documentable/Derived.pm6", + "Perl6::Documentable::Config": "lib/Perl6/Documentable/Config.pm6", + "Perl6::Documentable::Primary": "lib/Perl6/Documentable/Primary.pm6", + "Perl6::Documentable::Secondary": "lib/Perl6/Documentable/Secondary.pm6", "Perl6::Documentable::Index": "lib/Perl6/Documentable/Index.pm6", "Perl6::Documentable::Registry": "lib/Perl6/Documentable/Registry.pm6", "Perl6::Documentable::Heading::Grammar": "lib/Perl6/Documentable/Heading/Grammar.pm6", @@ -35,6 +37,7 @@ "Perl6::Documentable::DocPage::Kind": "lib/Perl6/Documentable/DocPage/Kind.pm6", "Perl6::Documentable::DocPage::Index": "lib/Perl6/Documentable/DocPage/Index.pm6", "Perl6::Documentable::DocPage::Source": "lib/Perl6/Documentable/DocPage/Source.pm6", + "Perl6::Documentable::DocPage::Factory": "lib/Perl6/Documentable/DocPage/Factory.pm6", "Perl6::Documentable::To::HTML::Wrapper": "lib/Perl6/Documentable/To/HTML/Wrapper.pm6", "Perl6::Documentable::CLI": "lib/Perl6/Documentable/CLI.pm6", @@ -47,7 +50,7 @@ "template/header.html", "template/footer.html", "template/search_template.js", - "language-order-control.json" + "config.json" ], "source-url": "https://github.com/antoniogamiz/Perl6-Documentable.git", "tags": [], @@ -57,7 +60,8 @@ "Perl6::TypeGraph:ver<0.0.4>", "Pod::To::HTML:ver<0.6.1>", "Pod::To::Cached:<0.3.2>", - "URI:ver<0.2.2>" + "URI:ver<0.2.2>", + "JSON::Fast:ver<0.9.18>" ], - "version": "2.1.4" + "version": "2.2.0" } diff --git a/lib/Perl6/Documentable.pm6 b/lib/Perl6/Documentable.pm6 index 87bc2d6..7ac99a5 100644 --- a/lib/Perl6/Documentable.pm6 +++ b/lib/Perl6/Documentable.pm6 @@ -1,7 +1,9 @@ unit module Perl6::Documentable; #| Enum to classify all "kinds" of Perl6::Documentable -enum Kind is export ; +enum Kind is export (Type => "type" , Language => "language", + Programs => "programs" , Syntax => "syntax" , + Reference => "reference", Routine => "routine" ); #| List of the subdirectories that contain indexable pods by default constant DOCUMENTABLE-DIRS is export = ["Language", "Type", "Programs", "Native"]; diff --git a/lib/Perl6/Documentable/CLI.pm6 b/lib/Perl6/Documentable/CLI.pm6 index 50e824c..6919dbf 100644 --- a/lib/Perl6/Documentable/CLI.pm6 +++ b/lib/Perl6/Documentable/CLI.pm6 @@ -1,10 +1,8 @@ use Perl6::Documentable; use Perl6::Documentable::Registry; -use Perl6::Documentable::DocPage::Source; -use Perl6::Documentable::DocPage::Kind; -use Perl6::Documentable::DocPage::Index; -use Perl6::Documentable::To::HTML::Wrapper; +use Perl6::Documentable::Config; +use Perl6::Documentable::DocPage::Factory; use Pod::Load; use Pod::To::Cached; @@ -44,18 +42,19 @@ package Perl6::Documentable::CLI { #| Start the documentation generation with the specified options multi MAIN ( "start" , - Str :$topdir = "doc", #= Directory where the pod collection is stored - Bool :v(:verbose($v)) = False, #= Prints progress information - Bool :c(:$cache) = True , #= Enables the use of a precompiled cache - Bool :p(:pods($p)) = False, #= Generates the HTML files corresponding to sources - Bool :k(:kind($k)) = False, #= Generates per kind files - Bool :s(:search-index($s)) = False, #= Generates the search index - Bool :i(:indexes($i)) = False, #= Generates the indexes files - Bool :t(:type-images($t)) = False, #= Write typegraph visualizations - Bool :f(:force($f)) = False, #= Force the regeneration of the typegraph visualizations - Bool :$highlight = False, #= Highlights the code blocks - Bool :$manage = False, #= Sort Language page - Bool :a(:$all) = False #= Equivalent to -t -p -k -i -s + Str :$topdir = "doc", #= Directory where the pod collection is stored + Str :$conf = "config.json", #= Configuration file + Bool :v(:verbose($v)) = False, #= Prints progress information + Bool :c(:$cache) = True , #= Enables the use of a precompiled cache + Bool :p(:pods($p)) = False, #= Generates the HTML files corresponding to sources + Bool :k(:kind($k)) = False, #= Generates per kind files + Bool :s(:search-index($s)) = False, #= Generates the search index + Bool :i(:indexes($i)) = False, #= Generates the indexes files + Bool :t(:type-images($t)) = False, #= Write typegraph visualizations + Bool :f(:force($f)) = False, #= Force the regeneration of the typegraph visualizations + Bool :$highlight = False, #= Highlights the code blocks + Bool :$manage = False, #= Sort Language page + Bool :a(:$all) = False #= Equivalent to -t -p -k -i -s ) { if (!"./html".IO.e || !"./assets".IO.e) { say q:to/END/; @@ -66,13 +65,17 @@ package Perl6::Documentable::CLI { END exit(1); } - #=================================================================== - my @docs; # all these doducments will be written in disk - #=================================================================== + #==========================setup==================================== + + my $config = Perl6::Documentable::Config.new(filename => $conf); + # all these doducments will be written in disk + my @docs; # to track the time my $now; + #=================================================================== + # highlights workaround if ($highlight) { DEBUG("Starting highlight process...", $v); @@ -107,11 +110,13 @@ package Perl6::Documentable::CLI { $registry.compose; print-time("Processing pods", $now); + my $factory = Perl6::Documentable::DocPage::Factory.new(:$config, :$registry); + #=================================================================== DEBUG("Writing html/index.html and html/404.html...", $v); - spurt 'html/index.html', p2h(load($topdir~'/HomePage.pod6')[0], :pod-path('HomePage.pod6')); - spurt 'html/404.html', p2h(load($topdir~'/404.pod6')[0], :pod-path('404.pod6')); + @docs.push($factory.generate-home-page() ); + @docs.push($factory.generate-error-page()); #=================================================================== @@ -120,17 +125,7 @@ package Perl6::Documentable::CLI { DEBUG("Generating source files...", $v); @docs.append: $registry.documentables.map(-> $doc { - given $doc.kind { - when Kind::Type { - Perl6::Documentable::DocPage::Source::Type.new.render($registry, $doc.name); - } - when Kind::Language { - Perl6::Documentable::DocPage::Source::Language.new.render($registry, $doc.name); - } - when Kind::Programs { - Perl6::Documentable::DocPage::Source::Programs.new.render($registry, $doc.name); - } - } + $factory.generate-primary($doc) }).Slip; print-time("Generate source files", $now); @@ -142,8 +137,8 @@ package Perl6::Documentable::CLI { $now = now; DEBUG("Generating per kind files...", $v); for Kind::Routine, Kind::Syntax -> $kind { - @docs.append: $registry.lookup($kind.gist, :by).map({.name}).unique.map(-> $name { - Perl6::Documentable::DocPage::Kind.new.render($registry, $name, $kind) + @docs.append: $registry.lookup($kind.Str, :by).map({.name}).unique.map(-> $name { + $factory.generate-secondary($kind, $name) }).Slip; } print-time("Generate per kind files", $now); @@ -155,21 +150,18 @@ package Perl6::Documentable::CLI { $now = now; DEBUG("Generating indexes...", $v); - # main indexes - @docs.push(Perl6::Documentable::DocPage::Index::Language.new.render($registry, $manage)); - @docs.push(Perl6::Documentable::DocPage::Index::Programs.new.render($registry)); - @docs.push(Perl6::Documentable::DocPage::Index::Type.new.render($registry)); - @docs.push(Perl6::Documentable::DocPage::Index::Routine.new.render($registry)); + @docs.push($factory.generate-index(Kind::Language, $manage)); + @docs.push($factory.generate-index(Kind::Type )); + @docs.push($factory.generate-index(Kind::Programs )); + @docs.push($factory.generate-index(Kind::Routine )); # subindexes for -> $category { - @docs.push( - Perl6::Documentable::DocPage::SubIndex::Type.new.render($registry, $category) - )} + @docs.push($factory.generate-subindex(Kind::Type, $category)) + } for -> $category { - @docs.push( - Perl6::Documentable::DocPage::SubIndex::Routine.new.render($registry, $category) - )} + @docs.push( $factory.generate-subindex(Kind::Routine, $category)) + } print-time("Generating index files", $now); } @@ -194,19 +186,20 @@ package Perl6::Documentable::CLI { #| Check which pod files have changed and regenerate its HTML files. multi MAIN ( "update", - Str :$topdir = "doc", #= Directory where the pod collection is stored - :$manage = True #= Sort Language page + Str :$topdir = "doc", #= Directory where the pod collection is stored + Bool :$manage = True, #= Sort Language page + Str :$conf = "config.json" #= Configuration file ) { DEBUG("Checking for changes..."); my $now = now; - my $cache = Pod::To::Cached.new(:path(".{$topdir}"), :verbose, :source($topdir)); + my $cache = Pod::To::Cached.new(:path(".cache-{$topdir}"), :verbose, :source($topdir)); my @files = $cache.list-files(); - { + if (! @files) { DEBUG("Everything already updated. There are no changes."); exit 0; - } unless @files; + } DEBUG(+@files ~ " file(s) modified. Starting regeneratiion ..."); @@ -218,63 +211,46 @@ package Perl6::Documentable::CLI { ); $registry.compose; + # configuration + my $config = Perl6::Documentable::Config.new(filename => $conf); + my $factory = Perl6::Documentable::DocPage::Factory.new(:$config, :$registry); my @docs; # files to write my @kinds; # to know what indexes to regenerate - # regenerate source files and per kind files - state %syntax-docs = $registry.lookup(Kind::Syntax.gist, :by) - .categorize({.name}); - state %routine-docs = $registry.lookup(Kind::Routine.gist, :by) - .categorize({.name}); + for @files -> $filename { my $doc = $registry.documentables.grep({ .url.lc eq "/" ~ $filename.lc # language/something type/Any }).first; - given $doc.kind { # source - when Kind::Type { - @docs.push(Perl6::Documentable::DocPage::Source::Type.new.render($registry, $doc.name)); - } - when Kind::Language { - @docs.push(Perl6::Documentable::DocPage::Source::Language.new.render($registry, $doc.name)); - } - when Kind::Programs { - @docs.push(Perl6::Documentable::DocPage::Source::Programs.new.render($registry, $doc.name)); - } - } + @docs.push($factory.generate-primary($doc)); + # per kind my @routine-docs = $doc.defs.grep({.kind eq Kind::Routine}).map({.name}); - @docs.push: @routine-docs.map(-> $name { - Perl6::Documentable::DocPage::Kind.new.render($registry, $name, Kind::Routine) - }).Slip; + @docs.push: @routine-docs.map(-> $name { $factory.generate-secondary(Kind::Routine, $name) }).Slip; + my @syntax-docs = $doc.defs.grep({.kind eq Kind::Syntax}).map({.name}); - @docs.push: @syntax-docs.map(-> $name { - Perl6::Documentable::DocPage::Kind.new.render($registry, $name, Kind::Syntax) - }).Slip; + @docs.push: @syntax-docs.map(-> $name { $factory.generate-secondary(Kind::Syntax, $name) }).Slip; + } #regenerate indexes - @docs.push(Perl6::Documentable::DocPage::Index::Routine.new.render($registry)); + @docs.push($factory.generate-index(Kind::Routine)); for -> $category { - @docs.push( - Perl6::Documentable::DocPage::SubIndex::Routine.new.render($registry, $category) - )} + @docs.push($factory.generate-subindex(Kind::Routine, $category)); + } for @kinds -> $kind { given $kind { - when Kind::Language { - @docs.push(Perl6::Documentable::DocPage::Index::Language.new.render($registry, $manage)); - } - when Kind::Programs { - @docs.push(Perl6::Documentable::DocPage::Index::Programs.new.render($registry)); - } + when Kind::Language { @docs.push($factory.generate-index(Kind::Language, $manage)); } + when Kind::Programs { @docs.push($factory.generate-index(Kind::Programs)); } when Kind::Type { - @docs.push(Perl6::Documentable::DocPage::Index::Type.new.render($registry)); + @docs.push($factory.generate-index(Kind::Type)); for -> $category { - @docs.push( - Perl6::Documentable::DocPage::SubIndex::Type.new.render($registry, $category) - )} + @docs.push( $factory.generate-subindex(Kind::Type, $category) ) + } } } } + @docs.map(-> $doc { spurt "html{$doc}.html", $doc }); print-time("Updating files", $now); } @@ -289,7 +265,6 @@ package Perl6::Documentable::CLI { && rm app.pl && rm app-start && rm Makefile \ && rm -rf template END - } } diff --git a/lib/Perl6/Documentable/Config.pm6 b/lib/Perl6/Documentable/Config.pm6 new file mode 100644 index 0000000..8838a48 --- /dev/null +++ b/lib/Perl6/Documentable/Config.pm6 @@ -0,0 +1,48 @@ +unit module Perl6::Documentable::Config; + +use Perl6::Documentable; +use Perl6::Documentable::Utils::IO; +use JSON::Fast; + + +class X::Documentable::Config::InvalidConfig is Exception { + + has $.msg; + + method message() { + $.msg; + } +} + +class Perl6::Documentable::Config { + + has %.config; + has @.kinds; + has $.filename; + + submethod BUILD (Str :$filename) { + my $json = slurp zef-path($filename); + %!config = from-json($json); + @!kinds = %!config.list; + die X::Documentable::Config::InvalidConfig.new("'kinds' entry missing") + unless %!config; + + for -> $kind { + die X::Documentable::Config::InvalidConfig.new("$kind entry missing inside 'kinds'") + unless %!config.grep({. eq $kind}); + } + } + + method get-kind-config(Kind $kind) { + return %() unless $kind; + my @results = @!kinds.grep({. eq $kind.Str}); + return @results.first if @results; + return %() + } + + method get-categories(Kind $kind) { + my $kind-conf = self.get-kind-config($kind); + return $kind-conf.list if $kind-conf; + return (); + } +} \ No newline at end of file diff --git a/lib/Perl6/Documentable/DocPage/Factory.pm6 b/lib/Perl6/Documentable/DocPage/Factory.pm6 new file mode 100644 index 0000000..b6f94fa --- /dev/null +++ b/lib/Perl6/Documentable/DocPage/Factory.pm6 @@ -0,0 +1,130 @@ +unit module Perl6::Documentable::DocPage::Factory; + +use Perl6::Documentable; +use Pod::Load; +use Perl6::Documentable::Config; +use Perl6::Documentable::Utils::IO; +use Perl6::Documentable::Registry; + +# html generation +use Perl6::Documentable::To::HTML::Wrapper; +use Perl6::Documentable::DocPage::Source; +use Perl6::Documentable::DocPage::Kind; +use Perl6::Documentable::DocPage::Index; + +class Perl6::Documentable::DocPage::Factory { + + has Perl6::Documentable::Config $.config; + has Perl6::Documentable::Registry $.registry; + has Perl6::Documentable::To::HTML::Wrapper $.wrapper; + + method BUILD( + Perl6::Documentable::Config :$!config, + Perl6::Documentable::Registry :$registry + ) { + $!registry = $registry; + $!wrapper = Perl6::Documentable::To::HTML::Wrapper.new(:$!config) + } + + method generate-home-page() { + my $pod = load($!registry.topdir~"/HomePage.pod6")[0]; + %( + document => $!wrapper.render($pod, :pod-path("HomePage.pod6")), + url => '/index' + ) + } + + method generate-error-page() { + my $pod = load($!registry.topdir~"/404.pod6")[0]; + %( + document => $!wrapper.render($pod, :pod-path("404.pod6")), + url => '/404' + ) + } + + method generate-primary($doc) { + my %pod-to-render = do given $doc.kind { + when Kind::Type { + Perl6::Documentable::DocPage::Source::Type.new.render($!registry, $doc.name); + } + when Kind::Language { + Perl6::Documentable::DocPage::Source::Language.new.render($!registry, $doc.name); + } + when Kind::Programs { + Perl6::Documentable::DocPage::Source::Programs.new.render($!registry, $doc.name); + } + } + + my Str $html = $!wrapper.render( %pod-to-render, + $doc.kind.Str, + :pod-path-from-url($doc.url), + disable-submenu => $doc.kind eq Kind::Language + ); + return %( + document => $html, + url => %pod-to-render + ) + } + + method generate-secondary(Kind $kind, Str $name) { + my %pod-to-render = Perl6::Documentable::DocPage::Kind.new.render($!registry, $name, $kind); + my Str $html = $!wrapper.render( %pod-to-render, + $kind.Str, + ); + return %( + document => $html, + url => %pod-to-render + ) + } + + method generate-index(Kind $kind, $manage?) { + my %pod-to-render = do given $kind { + when Kind::Type { + Perl6::Documentable::DocPage::Index::Type.new.render($!registry); + } + when Kind::Language { + my @categories = $!config.get-categories(Kind::Language); + Perl6::Documentable::DocPage::Index::Language.new.render( + $!registry, + $!config.get-kind-config(Kind::Language).sort || False, + @categories + ); + } + when Kind::Programs { + Perl6::Documentable::DocPage::Index::Programs.new.render($!registry); + } + when Kind::Routine { + Perl6::Documentable::DocPage::Index::Routine.new.render($!registry); + } + } + + my Str $html = $!wrapper.render( %pod-to-render, + $kind.Str, + ); + return %( + document => $html, + url => %pod-to-render + ) + } + + method generate-subindex(Kind $kind, $category) { + my %pod-to-render = do given $kind { + when Kind::Routine { + Perl6::Documentable::DocPage::SubIndex::Routine.new.render($!registry, $category); + } + when Kind::Type { + Perl6::Documentable::DocPage::SubIndex::Type.new.render($!registry, $category); + } + } + + my Str $html = $!wrapper.render( %pod-to-render, + $kind.Str, + ); + return %( + document => $html, + url => %pod-to-render + ) + } + + +} \ No newline at end of file diff --git a/lib/Perl6/Documentable/DocPage/Index.pm6 b/lib/Perl6/Documentable/DocPage/Index.pm6 index 94c32ad..10bc35e 100644 --- a/lib/Perl6/Documentable/DocPage/Index.pm6 +++ b/lib/Perl6/Documentable/DocPage/Index.pm6 @@ -1,53 +1,52 @@ unit module Perl6::Documentable::DocPage::Index; -use URI::Escape; -use Pod::Utilities::Build; use Perl6::Documentable; -use Perl6::Documentable::To::HTML::Wrapper; +use JSON::Fast; +use URI::Escape; +use Pod::Utilities::Build; class Perl6::Documentable::DocPage::Index::Language does Perl6::Documentable::DocPage { method compose($registry) { - $registry.lookup(Kind::Language.gist, :by).map({%( + $registry.lookup(Kind::Language.Str, :by).map({%( name => .name, url => .url, summary => .summary )}).cache; } - method render($registry, $manage = False) { + method generate-section($registry, %category) { + my $heading = pod-heading(%category, :level(2)); + my @docs = $registry.lookup(Kind::Language.Str, :by) + .grep({.categories eq %category}); + my @table = @docs.map(-> $doc { + [pod-link($doc.name, $doc.url), $doc.summary] + }); + + [$heading, pod-table(@table)] + } + + method render($registry, $manage = False, @categories = []) { my @index = self.compose($registry); my @content = []; if ($manage) { - my $path = "resources/language-order-control.json".IO.e ?? - "resources/language-order-control.json" !! - %?RESOURCES; - my $json = slurp $path; - my @data = from-json($json).list; - for @data -> %section { - @content.push: [ - pod-heading( %section.
, :level(2)), - pod-table( - %section..cache.map(-> %p { - my %i = @index.grep({$_. eq %p.})[0]; - [pod-link(%i., %i.), %i.] - })) - ] + for @categories -> %category { + @content.push: self.generate-section($registry, %category); } } else { @content = pod-table(@index.map({[ pod-link(., .), . ]})) } - my $page = p2h(pod-with-title( + my $pod = pod-with-title( 'Perl 6 Language Documentation', pod-block("Tutorials, general reference, migration guides and meta pages for the Perl 6 language."), @content - ), "language"); + ); - return %(document => $page, url => self.url); + return %(document => $pod, url => self.url); } method url() {return "/language"} @@ -57,7 +56,7 @@ class Perl6::Documentable::DocPage::Index::Programs does Perl6::Documentable::DocPage { method compose($registry) { - $registry.lookup(Kind::Programs.gist, :by).map({%( + $registry.lookup(Kind::Programs.Str, :by).map({%( name => .name, url => .url, summary => .summary @@ -66,14 +65,14 @@ class Perl6::Documentable::DocPage::Index::Programs method render($registry) { my @index = self.compose($registry); - my $page = p2h(pod-with-title( + my $pod = pod-with-title( 'Perl 6 Programs Documentation', pod-table(@index.map({[ pod-link(., .), . ]})) - ), "programs"); + ); - return %(document => $page, url => self.url); + return %(document => $pod, url => self.url); } method url() {return "/programs"} @@ -84,7 +83,7 @@ class Perl6::Documentable::DocPage::Index::Type method compose($registry) { [ - $registry.lookup(Kind::Type.gist, :by)\ + $registry.lookup(Kind::Type.Str, :by)\ .categorize(*.name).sort(*.key)>>.value .map({%( name => .[0].name, @@ -98,7 +97,7 @@ class Perl6::Documentable::DocPage::Index::Type method render($registry) { my @index = self.compose($registry); - my $page = p2h(pod-with-title( + my $pod = pod-with-title( "Perl 6 Types", pod-block( 'This is a list of ', pod-bold('all'), ' built-in Types' ~ @@ -112,9 +111,9 @@ class Perl6::Documentable::DocPage::Index::Type . ne "role" ?? . !! Pod::FormattingCode.new(:type, contents => [.]) ]}) ) - ), "type"); + ); - return %(document => $page, url => self.url); + return %(document => $pod, url => self.url); } method url() {return "/type"} @@ -124,7 +123,7 @@ class Perl6::Documentable::DocPage::SubIndex::Type does Perl6::Documentable::DocPage { method compose($registry, $category) { - $registry.lookup(Kind::Type.gist, :by)\ + $registry.lookup(Kind::Type.Str, :by)\ .grep({$category ⊆ .categories})\ # XXX .categorize(*.name).sort(*.key)>>.value .map({%( @@ -138,7 +137,7 @@ class Perl6::Documentable::DocPage::SubIndex::Type method render($registry, $category) { my @index = self.compose($registry, $category); - my $page = p2h(pod-with-title( + my $pod = pod-with-title( "Perl 6 $category Types", pod-table( @index.map({[ @@ -147,9 +146,9 @@ class Perl6::Documentable::DocPage::SubIndex::Type . ne "role" ?? . !! Pod::FormattingCode.new(:type, contents => [.]) ]}) ) - ), "type"); + ); - return %(document => $page, url => self.url($category)); + return %(document => $pod, url => self.url($category)); } method url($category) {return "/type-$category"} @@ -160,7 +159,7 @@ class Perl6::Documentable::DocPage::Index::Routine method compose($registry) { [ - $registry.lookup(Kind::Routine.gist, :by)\ + $registry.lookup(Kind::Routine.Str, :by)\ .categorize(*.name).sort(*.key)>>.value .map({%( name => .[0].name, @@ -173,7 +172,7 @@ class Perl6::Documentable::DocPage::Index::Routine method render($registry) { my @index = self.compose($registry); - my $page = p2h(pod-with-title( + my $pod = pod-with-title( "Perl 6 Routines", pod-block( 'This is a list of ', pod-bold('all'), ' built-in routines' ~ @@ -189,9 +188,9 @@ class Perl6::Documentable::DocPage::Index::Routine }).reduce({$^a,", ",$^b}),")") ]}) ) - ), "routine"); + ); - return %(document => $page, url => self.url); + return %(document => $pod, url => self.url); } method url() {return "/routine"} @@ -201,7 +200,7 @@ class Perl6::Documentable::DocPage::SubIndex::Routine does Perl6::Documentable::DocPage { method compose($registry, $category) { - $registry.lookup(Kind::Routine.gist, :by)\ + $registry.lookup(Kind::Routine.Str, :by)\ .grep({$category ⊆ .categories})\ # XXX .categorize(*.name).sort(*.key)>>.value .map({%( @@ -214,7 +213,7 @@ class Perl6::Documentable::DocPage::SubIndex::Routine method render($registry, $category) { my @index = self.compose($registry, $category); - my $page = p2h(pod-with-title( + my $pod = pod-with-title( "Perl 6 $category Routines", pod-table( @index.map({[ @@ -225,9 +224,9 @@ class Perl6::Documentable::DocPage::SubIndex::Routine }).reduce({$^a,", ",$^b}),")") ]}) ) - ), "routine"); + ); - return %(document => $page, url => self.url($category)); + return %(document => $pod, url => self.url($category)); } method url($category) {return "/routine-$category"} diff --git a/lib/Perl6/Documentable/DocPage/Kind.pm6 b/lib/Perl6/Documentable/DocPage/Kind.pm6 index 6762eb9..54c9d28 100644 --- a/lib/Perl6/Documentable/DocPage/Kind.pm6 +++ b/lib/Perl6/Documentable/DocPage/Kind.pm6 @@ -3,14 +3,13 @@ unit module Perl6::Documentable::DocPage::Kind; use URI::Escape; use Pod::Utilities::Build; use Perl6::Documentable; -use Perl6::Documentable::To::HTML::Wrapper; class Perl6::Documentable::DocPage::Kind does Perl6::Documentable::DocPage { method compose($name, @docs, $kind) { my @subkinds = @docs.map({slip .subkinds}).unique; - my $subkind = @subkinds == 1 ?? @subkinds[0] !! $kind.gist; + my $subkind = @subkinds == 1 ?? @subkinds[0] !! $kind.Str; my $pod = pod-with-title( "$subkind $name", pod-block("Documentation for $subkind ", pod-code($name), " assembled from the following types:"), @@ -37,15 +36,15 @@ class Perl6::Documentable::DocPage::Kind } method render($registry, $name, $kind) { - my %documents = $registry.lookup($kind.gist, :by) + my %documents = $registry.lookup($kind.Str, :by) .categorize({.name}); return %( - document => p2h(self.compose($name, %documents{$name}, $kind), $kind) , + document => self.compose($name, %documents{$name}, $kind), url => self.url($name, $kind) ); } method url($name, $kind) { - "/{$kind.gist.lc}/{good-name($name)}" + "/{$kind.Str.lc}/{good-name($name)}" } } \ No newline at end of file diff --git a/lib/Perl6/Documentable/DocPage/Source.pm6 b/lib/Perl6/Documentable/DocPage/Source.pm6 index 6c14768..34332dd 100644 --- a/lib/Perl6/Documentable/DocPage/Source.pm6 +++ b/lib/Perl6/Documentable/DocPage/Source.pm6 @@ -4,7 +4,6 @@ use Perl6::Documentable::Utils::IO; use URI::Escape; use Pod::Utilities::Build; use Perl6::Documentable; -use Perl6::Documentable::To::HTML::Wrapper; class Perl6::Documentable::DocPage::Source::Language does Perl6::Documentable::DocPage { @@ -14,7 +13,7 @@ class Perl6::Documentable::DocPage::Source::Language my $doc = @docs.grep({.name eq $name})[0]; my $pod-path = pod-path-from-url($doc.url); return %( - document => p2h($doc.pod, $doc.kind, :pod-path($pod-path)), + document => $doc.pod, url => self.url($doc) ); } @@ -32,7 +31,7 @@ class Perl6::Documentable::DocPage::Source::Programs my $doc = @docs.grep({.name eq $name})[0]; my $pod-path = pod-path-from-url($doc.url); return %( - document => p2h($doc.pod, $doc.kind, :pod-path($pod-path)), + document => $doc.pod, url => self.url($doc) ); } @@ -154,7 +153,7 @@ class Perl6::Documentable::DocPage::Source::Type self.compose-type($registry, $doc); my $pod-path = pod-path-from-url($doc.url); return %( - document => p2h($doc.pod, $doc.kind, :pod-path($pod-path)), + document => $doc.pod, url => self.url($doc) ); } diff --git a/lib/Perl6/Documentable/File.pm6 b/lib/Perl6/Documentable/Primary.pm6 similarity index 96% rename from lib/Perl6/Documentable/File.pm6 rename to lib/Perl6/Documentable/Primary.pm6 index 96fbef8..67bc4e3 100644 --- a/lib/Perl6/Documentable/File.pm6 +++ b/lib/Perl6/Documentable/Primary.pm6 @@ -1,5 +1,5 @@ use Perl6::Documentable; -use Perl6::Documentable::Derived; +use Perl6::Documentable::Secondary; use Perl6::Documentable::Index; use Perl6::Documentable::Heading::Grammar; use Perl6::Documentable::Heading::Actions; @@ -34,7 +34,7 @@ class X::Documentable::MissingMetadata is Exception { } } -class Perl6::Documentable::File is Perl6::Documentable { +class Perl6::Documentable::Primary is Perl6::Documentable { has Str $.summary; has Str $.url; @@ -52,7 +52,8 @@ class Perl6::Documentable::File is Perl6::Documentable { die X::Documentable::MissingMetadata.new(:$filename, metadata => "kind") unless self.check-metadata($pod); - my $kind = Kind(Kind.enums{ $pod.config }); + my $kind = Kind( $pod.config.lc ); + my $url = "/{$kind.lc}/$filename"; # proper name from =TITLE @@ -157,7 +158,7 @@ class Perl6::Documentable::File is Perl6::Documentable { next unless %attr; # At this point we have a valid definition - my $created = Perl6::Documentable::Derived.new( + my $created = Perl6::Documentable::Secondary.new( :origin(self), :pod[], |%attr diff --git a/lib/Perl6/Documentable/Registry.pm6 b/lib/Perl6/Documentable/Registry.pm6 index b8c8b11..294cdf1 100644 --- a/lib/Perl6/Documentable/Registry.pm6 +++ b/lib/Perl6/Documentable/Registry.pm6 @@ -7,7 +7,7 @@ use URI::Escape; use Perl6::Documentable::Utils::IO; use Perl6::TypeGraph; use Perl6::Documentable; -use Perl6::Documentable::File; +use Perl6::Documentable::Primary; use Perl6::Documentable::LogTimelineSchema; @@ -67,7 +67,7 @@ submethod BUILD ( } } -method add-new(Perl6::Documentable::File :$doc --> Perl6::Documentable::File) { +method add-new(Perl6::Documentable::Primary :$doc --> Perl6::Documentable::Primary) { die "Cannot add something to a composed registry" if $.composed; @!documentables.append: $doc; $doc; @@ -96,7 +96,7 @@ method process-pod-dir(Str :$dir --> Array) { my @pod-fragments = self.load(path => $file.path); for @pod-fragments -> $pod { Perl6::Documentable::LogTimeline::New.log: :$filename, -> { - my $doc =Perl6::Documentable::File.new( + my $doc =Perl6::Documentable::Primary.new( pod => $pod, filename => $filename, ); @@ -126,7 +126,7 @@ method lookup(Str $what, Str :$by!) { %!cache{$by}{$d."$by"()}.append: $d; } } - %!cache{$by}{$what.gist} // []; + %!cache{$by}{$what} // []; } method docs-for(Str $name) { diff --git a/lib/Perl6/Documentable/Derived.pm6 b/lib/Perl6/Documentable/Secondary.pm6 similarity index 95% rename from lib/Perl6/Documentable/Derived.pm6 rename to lib/Perl6/Documentable/Secondary.pm6 index d796a8d..f9a7dea 100644 --- a/lib/Perl6/Documentable/Derived.pm6 +++ b/lib/Perl6/Documentable/Secondary.pm6 @@ -2,7 +2,7 @@ use Perl6::Documentable; use Pod::Utilities; use Pod::Utilities::Build; -unit class Perl6::Documentable::Derived is Perl6::Documentable; +unit class Perl6::Documentable::Secondary is Perl6::Documentable; has $.origin; diff --git a/lib/Perl6/Documentable/To/HTML/Wrapper.pm6 b/lib/Perl6/Documentable/To/HTML/Wrapper.pm6 index 27caf5c..ce9b1ed 100644 --- a/lib/Perl6/Documentable/To/HTML/Wrapper.pm6 +++ b/lib/Perl6/Documentable/To/HTML/Wrapper.pm6 @@ -1,47 +1,57 @@ use Perl6::Documentable::Utils::IO; +use Perl6::Documentable::Config; use Perl6::Documentable; use URI::Escape; use Pod::To::HTML; -unit module Perl6::Documentable::To::HTML::Wrapper; +unit class Perl6::Documentable::To::HTML::Wrapper; -# hardcoded menu (TODO => generate it automatically) -my @menu = ('language', '' ) => (), - ('type' , 'Types' ) => , - ('routine' , 'Routines') => , - ('programs', '' ) => (), - ('https://webchat.freenode.net/?channels=#perl6', 'Chat with us') => (); +has Str $.head; +has Str $.header; +has Str $.footer; -# templates -my $head-template-path = zef-path("template/head.html" ); -my $header-template-path = zef-path("template/header.html"); -my $footer-template-path = zef-path("template/footer.html"); +has Perl6::Documentable::Config $.config; -#| Return the HTML header for every page -sub header-html($current-selection, $pod-path) is export { - state $header = slurp $header-template-path; - my $menu-items = [~] - q[]; +submethod BUILD( + Perl6::Documentable::Config :$!config +) { + $!head = slurp zef-path("template/head.html" ); + $!header = slurp zef-path("template/header.html"); + $!footer = slurp zef-path("template/footer.html"); +} + +method menu-entry( + %entry, + Str $selected +) { + my $class = $selected eq %entry ?? "selected darker-green" !! ""; + my $href = "/" ~ %entry ~ ".html"; + qq[ { %entry } ] +} - my $sub-menu-items = ''; - state %sub-menus = @menu>>.key>>[0] Z=> @menu>>.value; - if %sub-menus{$current-selection} -> $_ { - $sub-menu-items = [~] - q[]; +method submenu-entry( + %entry, + $parent +) { + my $href = "/" ~ $parent ~ "-" ~ %entry ~ ".html"; + qq[ {%entry} ] +} + +method menu($selected, $pod-path?) { + # main menu + my @menu-entries = $!config.kinds; + my $menu-items = (self.menu-entry($_, $selected) for @menu-entries).join; + $menu-items = [~] q[]; + # sub menu + my $submenu-items = ''; + my @submenu = $!config.get-categories(Kind( $selected )); + if (@submenu and $selected ne "language") { + $submenu-items = [~] q[]; } my $edit-url = ""; @@ -53,48 +63,23 @@ sub header-html($current-selection, $pod-path) is export { ] } - $header.subst('MENU', $menu-items ~ $sub-menu-items) + + $!header.subst('MENU', $menu-items ~ $submenu-items) .subst('EDITURL', $edit-url) - .subst: 'CONTENT_CLASS', - 'content_' ~ ($pod-path - ?? $pod-path.subst(/\.pod6$/, '').subst(/\W/, '_', :g) - !! 'fragment'); } -#| Return the footer HTML for every page -sub footer-html($pod-path) is export { - my $footer = slurp $footer-template-path; - $footer.subst-mutate(/DATETIME/, ~DateTime.now.utc.truncated-to('seconds')); - my $pod-url; - my $edit-url; - my $gh-link = q[perl6/doc on GitHub]; - if not defined $pod-path { - $pod-url = "the sources at $gh-link"; - $edit-url = "."; - } - else { - $pod-url = "$pod-path\ at $gh-link"; - $edit-url = " or edit this page\."; - } - $footer.subst-mutate(/SOURCEURL/, $pod-url); - $footer.subst-mutate(/EDITURL/, $edit-url); - - state $source-commit = (qx/git rev-parse --short HEAD/.chomp unless !".git".IO.e) // ''; - - $footer.subst-mutate(:g, /SOURCECOMMIT/, $source-commit); - - return $footer; +method footer() { + $!footer.subst(/DATETIME/, ~DateTime.now.utc.truncated-to('seconds')); } -#| Main method to transform a Pod to HTML. -sub p2h($pod, $selection = 'nothing selected', :$pod-path = Nil) is export { - state $head = slurp $head-template-path; - pod2html $pod, - :url(&rewrite-url), - :$head, - :header(header-html($selection, $pod-path)), - :footer(footer-html($pod-path)), - :default-title("Perl 6 Documentation"), - :css-url(''), # disable Pod::To::HTML's default CSS - ; +method render($pod, $selected = '', :$pod-path?) { + pod2html( + $pod, + url => &rewrite-url, + head => $!head, + header => self.menu($selected, $pod-path), + footer => self.footer, + default-title => "Perl 6 Documentation", + css-url => '' + ) } \ No newline at end of file diff --git a/resources/config.json b/resources/config.json new file mode 100644 index 0000000..b75a191 --- /dev/null +++ b/resources/config.json @@ -0,0 +1,87 @@ +{ + "kinds": [ + { + "kind": "language", + "sort": "1", + "display-text": "Language", + "categories": [ + { + "name": "beginning", + "display-text": "At the beginning" + }, + { + "name": "migration", + "display-text": "Migration guides" + }, + { + "name": "tutorial", + "display-text": "Tutorials" + }, + { + "name": "fundamental", + "display-text": "Fundamental topics" + }, + { + "name": "advanced", + "display-text": "Advanced topics" + } + ] + }, + { + "kind": "type", + "display-text": "Types", + "categories": [ + { + "name": "basic", + "display-text": "Basic" + }, + { + "name": "composite", + "display-text": "Composite" + }, + { + "name": "domain-specific", + "display-text": "Domain-specific" + }, + { + "name": "exception", + "display-text": "Exceptions" + } + ] + }, + { + "kind": "routine", + "display-text": "Routines", + "categories": [ + { + "name": "sub", + "display-text": "Sub" + }, + { + "name": "method", + "display-text": "Method" + }, + { + "name": "term", + "display-text": "Term" + }, + { + "name": "operator", + "display-text": "Operator" + }, + { + "name": "trait", + "display-text": "Trait" + }, + { + "name": "submethod", + "display-text": "Submethod" + } + ] + }, + { + "kind": "programs", + "display-text": "Programs" + } + ] +} diff --git a/resources/language-order-control.json b/resources/language-order-control.json deleted file mode 100644 index 246efaa..0000000 --- a/resources/language-order-control.json +++ /dev/null @@ -1,320 +0,0 @@ -[ - { - "section": "At the beginning", - "pods": [ - { - "name": "Brief introduction", - "file": "intro" - }, - { - "name": "Perl 6 by example P6-101", - "file": "101-basics" - } - ] - }, - { - "section": "Migration guides", - "pods": [ - { - "name": "Perl 5 to Perl 6 guide - in a nutshell", - "file": "5to6-nutshell" - }, - { - "name": "Perl 5 to Perl 6 guide - overview", - "file": "5to6-overview" - }, - { - "name": "Perl 5 to Perl 6 guide - functions", - "file": "5to6-perlfunc" - }, - { - "name": "Perl 5 to Perl 6 guide - operators", - "file": "5to6-perlop" - }, - { - "name": "Perl 5 to Perl 6 guide - syntax", - "file": "5to6-perlsyn" - }, - { - "name": "Perl 5 to Perl 6 guide - special variables", - "file": "5to6-perlvar" - }, - { - "name": "Haskell to Perl 6 - nutshell", - "file": "haskell-to-p6" - }, - { - "name": "JavaScript (Node.js) to Perl 6 - nutshell", - "file": "js-nutshell" - }, - { - "name": "Python to Perl 6 - nutshell", - "file": "py-nutshell" - }, - { - "name": "Ruby to Perl 6 - nutshell", - "file": "rb-nutshell" - } - ] - }, - { - "section": "Tutorials", - "pods": [ - { - "name": "Classes and objects", - "file": "classtut" - }, - { - "name": "Command line interface", - "file": "create-cli" - }, - { - "name": "Concurrency", - "file": "concurrency" - }, - { - "name": "Core modules", - "file": "modules-core" - }, - { - "name": "Doing math with Perl 6", - "file": "math" - }, - { - "name": "Entering unicode characters", - "file": "unicode_entry" - }, - { - "name": "Grammar tutorial", - "file": "grammar_tutorial" - }, - { - "name": "Input/Output", - "file": "io" - }, - { - "name": "Inter-process communication", - "file": "ipc" - }, - { - "name": "Iterating", - "file": "iterating" - }, - { - "name": "Module development utilities", - "file": "modules-extra" - }, - { - "name": "Module packages", - "file": "module-packages" - }, - { - "name": "Modules", - "file": "modules" - }, - { - "name": "Creating operators", - "file": "optut" - }, - { - "name": "Regexes: best practices and gotchas", - "file": "regexes-best-practices" - } - ] - }, - { - "section": "General reference", - "pods": [ - { - "name": "About the docs", - "file": "about" - }, - { - "name": "Community", - "file": "community" - }, - { - "name": "FAQ", - "file": "faq" - }, - { - "name": "Glossary", - "file": "glossary" - }, - { - "name": "Perl 6 pod", - "file": "pod" - }, - { - "name": "Pod 6 tables", - "file": "tables" - }, - { - "name": "Terms", - "file": "terms" - }, - { - "name": "Testing", - "file": "testing" - }, - { - "name": "Traps to avoid", - "file": "traps" - } - ] - }, - { - "section": "Fundamental topics", - "pods": [ - { - "name": "Containers", - "file": "containers" - }, - { - "name": "Contexts and contextualizers", - "file": "contexts" - }, - { - "name": "Control flow", - "file": "control" - }, - { - "name": "Data structures", - "file": "structures" - }, - { - "name": "Date and time functions", - "file": "temporal" - }, - { - "name": "Enumeration", - "file": "enumeration" - }, - { - "name": "Exceptions", - "file": "exceptions" - }, - { - "name": "Functions", - "file": "functions" - }, - { - "name": "Grammars", - "file": "grammars" - }, - { - "name": "Hashes and maps", - "file": "hashmap" - }, - { - "name": "Input/Output the definitive guide", - "file": "io-guide" - }, - { - "name": "Lists, sequences, and arrays", - "file": "list" - }, - { - "name": "Meta-object protocol (MOP)", - "file": "mop" - }, - { - "name": "Native calling interface", - "file": "nativecall" - }, - { - "name": "Newline handling in Perl 6", - "file": "newline" - }, - { - "name": "Numerics", - "file": "numerics" - }, - { - "name": "Object orientation", - "file": "objects" - }, - { - "name": "Operators", - "file": "operators" - }, - { - "name": "Packages", - "file": "packages" - }, - { - "name": "Performance", - "file": "performance" - }, - { - "name": "Perl 6 native types", - "file": "nativetypes" - }, - { - "name": "Phasers", - "file": "phasers" - }, - { - "name": "Pragmas", - "file": "pragmas" - }, - { - "name": "Quoting constructs", - "file": "quoting" - }, - { - "name": "Regexes", - "file": "regexes" - }, - { - "name": "Sets, bags, and mixes", - "file": "setbagmix" - }, - { - "name": "Statement prefixes", - "file": "statement-prefixes" - }, - { - "name": "Subscripts", - "file": "subscripts" - }, - { - "name": "Syntax", - "file": "syntax" - }, - { - "name": "System interaction", - "file": "system" - }, - { - "name": "Traits", - "file": "traits" - }, - { - "name": "Type system", - "file": "typesystem" - }, - { - "name": "Unicode", - "file": "unicode" - }, - { - "name": "Unicode versus ASCII symbols", - "file": "unicode_ascii" - }, - { - "name": "Variables", - "file": "variables" - } - ] - }, - { - "section": "Advanced topics", - "pods": [ - { - "name": "Experimental features", - "file": "experimental" - } - ] - } -] \ No newline at end of file diff --git a/resources/template/footer.html b/resources/template/footer.html index d87783b..e44c4d4 100644 --- a/resources/template/footer.html +++ b/resources/template/footer.html @@ -1,12 +1,12 @@