package Statocles::Plugin::Highlight;
# ABSTRACT: Highlight code and configuration syntax
$Statocles::Plugin::Highlight::VERSION = '0.064';

use Statocles::Base 'Class';
with 'Statocles::Plugin';
BEGIN {
    eval { require Syntax::Highlight::Engine::Kate; 1 }
        or die "Error loading Statocles::Plugin::Highlight. To use this plugin, install Syntax::Highlight::Engine::Kate";
};


has style => (
    is => 'ro',
    isa => Str,
    default => "default",
);


my $hl = Syntax::Highlight::Engine::Kate->new(
    substitutions => {
        "<"  => "&lt;",
        ">"  => "&gt;",
        "&"  => "&amp;",
    },
    format_table => {
        Alert        => [ '', '' ],
        BaseN        => [ '<span class="hljs-number">', '</span>' ],
        BString      => [ '', '' ],
        Char         => [ '<span class="hljs-string">', '</span>' ],
        Comment      => [ '<span class="hljs-comment">', '</span>' ],
        DataType     => [ '<span class="hljs-type">', '</span>' ],
        DecVal       => [ '<span class="hljs-number">', '</span>' ],
        Error        => [ '', '' ],
        Float        => [ '<span class="hljs-number">', '</span>' ],
        Function     => [ '<span class="hljs-function">', '</span>' ],
        IString      => [ '', '' ],
        Keyword      => [ '<span class="hljs-keyword">', '</span>' ],
        Normal       => [ '', '' ],
        Operator     => [ '', '' ],
        Others       => [ '', '' ],
        RegionMarker => [ '', '' ],
        Reserved     => [ '<span class="hljs-built-in">', '</span>' ],
        String       => [ '<span class="hljs-string">', '</span>' ],
        Variable     => [ '<span class="hljs-variable">', '</span>' ],
        Warning      => [ '', '' ],
    },
);

sub highlight {
    my ( $self, $args, $type, $text ) = @_;

    # Handle Mojolicious begin/end
    if ( ref $text eq 'CODE' ) {
        $text = $text->();
        # This adds an extra newline to the first line, so remove it
        $text =~ s/^\n//;
    }

    # XXX We need to normalize this so that the current page is always
    # `$args->{page}`
    my $page = $args->{page} || $args->{self};
    if ( $page ) {
        # Add the appropriate stylesheet to the page
        my $style_url = $page->site->theme->url( '/plugin/highlight/' . $self->style . '.css' );
        if ( !grep { $_->href eq $style_url } $page->links( 'stylesheet' ) ) {
            $page->links( stylesheet => $style_url );
        }
    }

    # Find the right language
    # We can't use languagePlug for this because it will always write
    # a warning to the screen.
    # See https://rt.cpan.org/Ticket/Display.html?id=110836
    my $found_lang;
    for my $lang ( $hl->languageList ) {
        if ( lc $lang eq lc $type ) {
            $found_lang = $lang;
            last;
        }
    }
    if ( !$found_lang ) {
        die sprintf qq{Could not find language "%s"\n}, $type;
    }

    $hl->language( $found_lang );
    return $hl->highlightText( $text );
}


sub register {
    my ( $self, $site ) = @_;
    $site->theme->helper( highlight => sub { $self->highlight( @_ ) } );
}

1;

=pod

=head1 NAME

Statocles::Plugin::Highlight - Highlight code and configuration syntax

=head1 VERSION

version 0.064

=head1 SYNOPSIS

    # --- Configuration
    # site.yml
    ---
    site:
        class: Statocles::Site
        args:
            plugins:
                highlight:
                    $class: Statocles::Plugin::Highlight
                    $args:
                        style: default

    # --- Usage
    <pre><code class="hljs">
    <%= highlight perl => begin %>
    print "Hello, World!\n";
    <% end %>
    </code></pre>

=head1 DESCRIPTION

This plugin adds the C<highlight> helper function to all templates and
content documents, allowing for syntax highlighting of source code and
configuration blocks.

=head1 ATTRIBUTES

=head2 style

The style to use, which corresponds to a stylesheet file in your theme's
C</plugin/highlight> directory without the trailing C<.css>. Defaults to
C<"default">, which refers to the C<default.css> file.

The styles included by default are:

=over 4

=item *

default

=item *

solarized-light

=item *

solarized-dark

=back

=head1 METHODS

=head2 highlight

    %= highlight $type => $content

Highlight the given C<$content> using the given C<$type> syntax.

The list of supported syntaxes are in the L<SUPPORTED SYNTAX|/SUPPORTED
SYNTAX> section, below.

To highlight a block of code, use C<begin>/C<end>:

    %= highlight Perl => begin
    use strict;
    use warnings;
    print "Hello, World!\n";
    % end

To highlight an included file, use the C<include> helper:

    %= highlight Perl => include 'test.pl'

The highlight function does not add any C<pre> or C<code> tags, so you
can use it inline with other text. To make sure the background is
correct, add the C<hljs> class to the C<code> tag. For example:

    <p>The example Perl code
    <code class="hljs"><%= highlight Perl => 'print "Hello, World\n"' %></code>
    prints the string `Hello, World` to the screen,
    followed by a newline character.</p>

=head2 register

Register this plugin with the site. Called automatically.

=head1 SUPPORTED SYNTAX

All of the syntax types supported by the L<Syntax::Highlight::Engine::Kate> Perl module
are supported by this module:

    .desktop                ferite                  PHP/PHP
    4GL                     Fortran                 PicAsm
    4GL-PER                 FreeBASIC               Pike
    ABC                     GDL                     PostScript
    Ada                     GLSL                    POV-Ray
    AHDL                    GNU Assembler           progress
    Alerts                  GNU Gettext             Prolog
    ANSI C89                Haskell                 PureBasic
    Ansys                   HTML                    Python
    Apache Configuration    IDL                     Quake Script
    Asm6502                 ILERPG                  R Script
    ASP                     Inform                  RenderMan RIB
    AVR Assembler           INI Files               REXX
    AWK                     Intel x86 (NASM)        RPM Spec
    BaseTest                Java                    RSI IDL
    BaseTestchild           Javadoc                 Ruby
    Bash                    JavaScript              Sather
    BibTeX                  JavaScript/PHP          Scheme
    C                       JSP                     scilab
    C#                      Kate File Template      SGML
    C++                     KBasic                  Sieve
    Cg                      LaTeX                   SML
    CGiS                    LDIF                    Spice
    ChangeLog               Lex/Flex                SQL
    Cisco                   LilyPond                SQL (MySQL)
    Clipper                 Literate Haskell        SQL (PostgreSQL)
    CMake                   Logtalk                 Stata
    ColdFusion              LPC                     TaskJuggler
    Common Lisp             Lua                     Tcl/Tk
    Component-Pascal        M3U                     TI Basic
    CSS                     MAB-DB                  txt2tags
    CSS/PHP                 Makefile                UnrealScript
    CUE Sheet               Mason                   Velocity
    D                       Matlab                  Verilog
    Debian Changelog        MIPS Assembler          VHDL
    Debian Control          Modula-2                VRML
    de_DE                   Music Publisher         Wikimedia
    Diff                    nl                      WINE Config
    Doxygen                 Objective Caml          x.org Configuration
    E Language              Objective-C             xHarbour
    Eiffel                  Octave                  XML
    Email                   Pascal                  xslt
    en_US                   Perl                    yacas
    Euphoria                PHP (HTML)              Yacc/Bison

=head1 ATTRIBUTION

The C<default>, C<solarized-light>, and C<solarized-dark> styles are taken from
the L<Highlight.js project|https://highlightjs.org>, and are licensed under the
BSD license.

=head1 SEE ALSO

=over 4

=item L<Syntax::Highlight::Engine::Kate>

The underlying syntax highlighter powering this plugin

=back

=head1 AUTHOR

Doug Bell <preaction@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2016 by Doug Bell.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut

__END__

# Generate the list of languages supported with:
# perl -MSyntax::Highlight::Engine::Kate -E'say for Syntax::Highlight::Engine::Kate->new->languageList' | fmtcol -w72
# fmtcol comes from Term::FormatColumns


