File Coverage

blib/lib/Syntax/Highlight/RDF.pm
Criterion Covered Total %
statement 278 369 75.3
branch 113 216 52.3
condition 112 227 49.3
subroutine 57 74 77.0
pod 3 3 100.0
total 563 889 63.3


line stmt bran cond sub pod time code
1             package Syntax::Highlight::RDF;
2              
3 1     1   1199 use 5.010001;
  1         4  
  1         36  
4 1     1   5 use strict;
  1         1  
  1         33  
5 1     1   14 use warnings;
  1         2  
  1         68  
6              
7             BEGIN {
8 1     1   1 $Syntax::Highlight::RDF::AUTHORITY = 'cpan:TOBYINK';
9 1         404 $Syntax::Highlight::RDF::VERSION = '0.003';
10             }
11              
12 1         64 use MooX::Struct -retain, -rw,
13             Feature => [],
14             Token => [-extends => [qw<Feature>], qw($spelling!)],
15             Comment => [-extends => [qw<Token>]],
16             Brace => [-extends => [qw<Token>]],
17             Bracket => [-extends => [qw<Token>]],
18             Parenthesis => [-extends => [qw<Token>]],
19             Datatype => [-extends => [qw<Token>]],
20             AtRule => [-extends => [qw<Token>]],
21             Shorthand => [-extends => [qw<Token>]],
22             BNode => [-extends => [qw<Token>]],
23             Variable => [-extends => [qw<Token>]],
24             Number => [-extends => [qw<Token>]],
25             Number_Double => [-extends => [qw<Number>]],
26             Number_Decimal => [-extends => [qw<Number>]],
27             Number_Integer => [-extends => [qw<Number>]],
28             Punctuation => [-extends => [qw<Token>]],
29             Path => [-extends => [qw<Token>]],
30             Boolean => [-extends => [qw<Token>]],
31             Sparql => [-extends => [qw<Token>]],
32             Sparql_Keyword => [-extends => [qw<Sparql>]],
33             Sparql_Operator => [-extends => [qw<Sparql>]],
34             Sparql_Function => [-extends => [qw<Sparql>]],
35             Sparql_Aggregate => [-extends => [qw<Sparql_Function>]],
36             Sparql_Ordering => [-extends => [qw<Sparql_Function>]],
37             IsOf => [-extends => [qw<Token>]],
38             Language => [-extends => [qw<Token>]],
39             Unknown => [-extends => [qw<Token>]],
40             Whitespace => [-extends => [qw<Token>]],
41             Name => [-extends => [qw<Token>]],
42             URIRef => [-extends => [qw<Token>], qw($absolute_uri)],
43             CURIE => [-extends => [qw<Token>], qw($absolute_uri)],
44             String => [-extends => [qw<Token>], qw($quote_char $parts $language)],
45             LongString => [-extends => [qw<String>]],
46             ShortString => [-extends => [qw<String>]],
47             Structure_Start => [-extends => [qw<Feature>], qw($end)],
48             Structure_End => [-extends => [qw<Feature>], q($start) => [weak_ref => 1]],
49             PrefixDefinition_Start => [-extends => [qw<Structure_Start>], qw($prefix $absolute_uri)],
50             PrefixDefinition_End => [-extends => [qw<Structure_End>]],
51             Pretdsl => [-extends => [qw<Token>]],
52             Pretdsl_Perl_Dist => [-extends => [qw<Pretdsl>]],
53             Pretdsl_Perl_Release => [-extends => [qw<Pretdsl>]],
54             Pretdsl_Perl_File => [-extends => [qw<Pretdsl>]],
55             Pretdsl_Perl_Module => [-extends => [qw<Pretdsl>]],
56             Pretdsl_Perl_Package => [-extends => [qw<Pretdsl>]],
57             Pretdsl_RT => [-extends => [qw<Pretdsl>]],
58             Pretdsl_CPANID => [-extends => [qw<Pretdsl>]],
59             Pretdsl_Date => [-extends => [qw<Pretdsl>]],
60             Pretdsl_DateTime => [-extends => [qw<Pretdsl>]],
61             Pretdsl_Keyword => [-extends => [qw<Pretdsl>], qw($absolute_uri)],
62 1     1   4183552 ;
  1         23401200  
63              
64             use Throwable::Factory
65 1         10 Tokenization => [qw( $remaining -caller )],
66             NotImplemented => [qw( -notimplemented )],
67             WTF => [],
68             WrongInvocant => [qw( -caller )],
69 1     1   571036 ;
  1         121399  
70              
71             {
72 1     1   47293 use HTML::HTML5::Entities qw/encode_entities/;
  1         18243  
  1         95  
73 1     1   12 no strict 'refs';
  1         1  
  1         1442  
74            
75             my $unescape = sub
76             {
77             my $u = $_[0];
78             $u =~ s{
79             ( \\ ([\\nrt"]|U[A-Fa-f0-9]{8}|u[A-Fa-f0-9]{4}) )
80             }{
81             $2 eq "\\" ? "\\" :
82             $2 eq "n" ? "\n" :
83             $2 eq "r" ? "\r" :
84             $2 eq "t" ? "\t" :
85             $2 eq '"' ? "\"" :
86             chr hex("0x".substr($2, 1))
87             }exg;
88             return $u;
89             };
90            
91 0     0   0 *{Feature . "::tok"} = sub { sprintf "%s~", $_[0]->TYPE };
92 0     0   0 *{Token . "::tok"} = sub { sprintf "%s[%s]", $_[0]->TYPE, $_[0]->spelling };
93 0     0   0 *{Whitespace . "::tok"} = sub { $_[0]->TYPE };
94 0     0   0 *{Feature . "::TO_STRING"} = sub { "" };
95 0     0   0 *{Token . "::TO_STRING"} = sub { $_[0]->spelling };
96             *{Token . "::TO_HTML"} = sub {
97 25     25   2495 sprintf "<span class=\"rdf_%s\">%s</span>", lc $_[0]->TYPE, encode_entities($_[0]->spelling)
98             };
99 35     35   2994 *{Whitespace . "::TO_HTML"} = sub { $_[0]->spelling };
100 9     9   191 *{URIRef . "::uri"} = sub { my $u = $_[0]->spelling; $unescape->(substr $u, 1, length($u)-2) };
  9         252  
101 45     45   1124 *{CURIE . "::prefix"} = sub { (split ":", $_[0]->spelling)[0] };
102 19     19   405 *{CURIE . "::suffix"} = sub { (split ":", $_[0]->spelling)[1] };
103             *{PrefixDefinition_Start . "::tok"} = sub {
104 0     0   0 sprintf '%s{prefix:"%s",uri:"%s"}', $_[0]->TYPE, $_[0]->prefix, $_[0]->absolute_uri;
105             };
106             *{PrefixDefinition_End . "::tok"} = sub {
107 0     0   0 sprintf '%s{prefix:"%s",uri:"%s"}', $_[0]->TYPE, $_[0]->start->prefix, $_[0]->start->absolute_uri;
108             };
109             *{CURIE . "::tok"} = sub {
110 0   0 0   0 sprintf '%s[%s]{uri:"%s"}', $_[0]->TYPE, $_[0]->spelling, $_[0]->absolute_uri//"???";
111             };
112             *{URIRef . "::tok"} = sub {
113 0   0 0   0 sprintf '%s[%s]{uri:"%s"}', $_[0]->TYPE, $_[0]->spelling, $_[0]->absolute_uri//"???";
114             };
115             *{Structure_Start . "::TO_HTML"} = sub {
116 0     0   0 my @attrs = sprintf 'class="rdf_%s"', lc $_[0]->TYPE;
117 0         0 sprintf "<span %s>", join " ", @attrs;
118             };
119             *{Structure_End . "::TO_HTML"} = sub {
120 4     4   158 "</span>"
121             };
122             *{PrefixDefinition_Start . "::TO_HTML"} = sub {
123 4     4   37 my @attrs = sprintf 'class="rdf_%s"', lc $_[0]->TYPE;
124 4 50       82 push @attrs, sprintf 'data-rdf-prefix="%s"', encode_entities($_[0]->prefix) if defined $_[0]->prefix;
125 4 50       201 push @attrs, sprintf 'data-rdf-uri="%s"', encode_entities($_[0]->absolute_uri) if defined $_[0]->absolute_uri;
126 4         150 sprintf "<span %s>", join " ", @attrs;
127             };
128             *{CURIE . "::TO_HTML"} = sub {
129 9     9   75 my @attrs = sprintf 'class="rdf_%s"', lc $_[0]->TYPE;
130 9 50       53 push @attrs, sprintf 'data-rdf-prefix="%s"', encode_entities($_[0]->prefix) if defined $_[0]->prefix;
131 9 100       157 push @attrs, sprintf 'data-rdf-suffix="%s"', encode_entities($_[0]->suffix) if defined $_[0]->suffix;
132 9 50       1749 push @attrs, sprintf 'data-rdf-uri="%s"', encode_entities($_[0]->absolute_uri) if defined $_[0]->absolute_uri;
133 9         1736 sprintf "<span %s>%s</span>", join(" ", @attrs), encode_entities($_[0]->spelling)
134             };
135             *{URIRef . "::TO_HTML"} = sub {
136 7     7   60 my @attrs = sprintf 'class="rdf_%s"', lc $_[0]->TYPE;
137 7 50       151 push @attrs, sprintf 'data-rdf-uri="%s"', encode_entities($_[0]->absolute_uri) if defined $_[0]->absolute_uri;
138 7         396 sprintf "<span %s>%s</span>", join(" ", @attrs), encode_entities($_[0]->spelling)
139             };
140             *{Pretdsl_Keyword . "::TO_HTML"} = sub {
141 2     2   19 my @attrs = sprintf 'class="rdf_%s"', lc $_[0]->TYPE;
142 2 50       29 push @attrs, sprintf 'data-rdf-uri="%s"', encode_entities($_[0]->absolute_uri) if defined $_[0]->absolute_uri;
143 2         875 sprintf "<span %s>%s</span>", join(" ", @attrs), encode_entities($_[0]->spelling)
144             };
145             }
146              
147             our %STYLE = (
148             rdf_brace => 'color:#990000;font-weight:bold',
149             rdf_bracket => 'color:#990000;font-weight:bold',
150             rdf_parenthesis => 'color:#990000;font-weight:bold',
151             rdf_punctuation => 'color:#990000;font-weight:bold',
152             rdf_datatype => 'color:#990000;font-weight:bold',
153             rdf_atrule => 'color:#000000;font-weight:bold',
154             rdf_comment => 'color:#669933;font-style:italic',
155             rdf_isof => 'color:#000099;font-style:italic',
156             rdf_sparql_keyword => 'color:#000000;font-weight:bold;font-style:italic',
157             rdf_sparql_operator => 'color:#000000;font-weight:bold;font-style:italic',
158             rdf_sparql_function => 'color:#000000;font-weight:bold;font-style:italic',
159             rdf_sparql_aggregate => 'color:#000000;font-weight:bold;font-style:italic',
160             rdf_sparql_ordering => 'color:#000000;font-weight:bold;font-style:italic',
161             rdf_unknown => 'color:#ffff00;background-color:#660000;font-weight:bold',
162             rdf_uriref => 'color:#0000cc',
163             rdf_curie => 'color:#000099;font-weight:bold',
164             rdf_bnode => 'color:#009900;font-weight:bold',
165             rdf_shorthand => 'color:#000099;font-weight:bold;font-style:italic',
166             rdf_variable => 'color:#009900;font-weight:bold;font-style:italic',
167             rdf_shortstring => 'color:#cc00cc',
168             rdf_longstring => 'color:#cc00cc;background-color:#ffddff;font-style:italic',
169             rdf_language => 'color:#ff0000',
170             rdf_number_double => 'color:#cc00cc;font-weight:bold',
171             rdf_number_decimal => 'color:#cc00cc;font-weight:bold',
172             rdf_number_integer => 'color:#cc00cc;font-weight:bold',
173             rdf_boolean => 'color:#cc00cc;font-weight:bold;font-style:italic',
174             rdf_path => 'color:#000099;background-color:#99ffff;font-weight:bold',
175             rdf_name => 'color:#000099;background-color:#ffff99;font-weight:bold',
176             rdf_pretdsl_perl_dist => 'color:white;background:#FF9900;font-weight:bold',
177             rdf_pretdsl_perl_release => 'color:white;background:#FF6666;font-weight:bold',
178             rdf_pretdsl_perl_file => 'color:white;background:#00ff66;font-weight:bold',
179             rdf_pretdsl_perl_module => 'color:white;background:#00ff66;font-weight:bold',
180             rdf_pretdsl_perl_package => 'color:white;background:#000099;font-weight:bold',
181             rdf_pretdsl_rt => 'color:white;background:#990000;font-weight:bold',
182             rdf_pretdsl_cpanid => 'color:white;background:#009900;font-weight:bold',
183             rdf_pretdsl_date => 'color:#cc00cc;font-style:italic',
184             rdf_pretdsl_datetime => 'color:#cc00cc;font-style:italic',
185             rdf_pretdsl_keyword => 'color:#000099;font-weight:bold;font-style:italic',
186             );
187              
188 1     1   8 use Moo;
  1         2  
  1         10  
189              
190 1     1   12701 use IO::Detect qw( as_filehandle );
  1         27539  
  1         15  
191 1     1   422 use Scalar::Util qw( blessed );
  1         2  
  1         60  
192              
193             use constant {
194 1         149 MODE_NTRIPLES => 0,
195             MODE_TURTLE => 1,
196             MODE_NOTATION_3 => 2,
197             MODE_SPARQL => 4,
198             MODE_PRETDSL => 8,
199             MODE_TRIG => 16,
200 1     1   5 };
  1         2  
201              
202 1     1   5 use constant mode => (MODE_NTRIPLES | MODE_TURTLE | MODE_NOTATION_3 | MODE_SPARQL | MODE_PRETDSL | MODE_TRIG);
  1         2  
  1         81  
203              
204             has _remaining => (is => "rw");
205             has _tokens => (is => "rw");
206              
207             my ($nameStartChar, $nameStartChar2, $nameChar);
208             {
209 1     1   5 no warnings "utf8";
  1         2  
  1         10890  
210             $nameStartChar = qr{A-Za-z_\x{00C0}-\x{00D6}\x{00D8}-\x{00F6}\x{00F8}-\x{02FF}\x{0370}-\x{037D}\x{037F}-\x{1FFF}\x{200C}-\x{200D}\x{2070}-\x{218F}\x{2C00}-\x{2FEF}\x{3001}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFFD}\x{10000}-\x{EFFFF}};
211             $nameStartChar2 = qr{A-Za-yz\x{00C0}-\x{00D6}\x{00D8}-\x{00F6}\x{00F8}-\x{02FF}\x{0370}-\x{037D}\x{037F}-\x{1FFF}\x{200C}-\x{200D}\x{2070}-\x{218F}\x{2C00}-\x{2FEF}\x{3001}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFFD}\x{10000}-\x{EFFFF}};
212             $nameChar = qr{A-Za-z_\x{00C0}-\x{00D6}\x{00D8}-\x{00F6}\x{00F8}-\x{037D}\x{037F}-\x{1FFF}\x{200C}-\x{200D}\x{2070}-\x{218F}\x{2C00}-\x{2FEF}\x{3001}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFFD}\x{10000}-\x{EFFFF}\x{00B7}\x{203F}\x{2040}0-9-};
213             }
214              
215             our @sparqlQueryWord = qw(
216             BASE
217             PREFIX
218             SELECT
219             DISTINCT
220             REDUCED
221             AS
222             CONSTRUCT
223             WHERE
224             DESCRIBE
225             ASK
226             FROM
227             NAMED
228             GROUP__BY
229             HAVING
230             ORDER__BY
231             LIMIT
232             OFFSET
233             VALUES
234             DEFAULT
235             ALL
236             OPTIONAL
237             SERVICE
238             BIND
239             UNDEF
240             MINUS
241             FILTER
242             );
243              
244             our @sparqlUpdateWord = qw(
245             LOAD
246             SILENT
247             INTO
248             CLEAR
249             DROP
250             CREATE
251             ADD
252             MOVE
253             COPY
254             INSERT__DATA
255             DELETE__DATA
256             DELETE__WHERE
257             DELETE
258             INSERT
259             USING
260             );
261              
262             our @sparqlOperator = qw(
263             ||
264             &&
265             =
266             !=
267             <
268             >
269             <=
270             >=
271             NOT__IN
272             NOT
273             IN
274             +
275             -
276             *
277             /
278             !
279             );
280              
281             our @sparqlFunction = qw(
282             STR
283             LANG
284             LANGMATCHES
285             DATATYPE
286             BOUND
287             IRI
288             URI
289             BNODE
290             RAND
291             ABS
292             CEIL
293             FLOOR
294             ROUND
295             CONCAT
296             STRLEN
297             UCASE
298             LCASE
299             ENCODE_FOR_URI
300             CONTAINS
301             STRSTARTS
302             STRENDS
303             STRBEFORE
304             STRAFTER
305             YEAR
306             MONTH
307             DAY
308             HOURS
309             MINUTES
310             SECONDS
311             TIMEZONE
312             TZ
313             NOW
314             UUID
315             STRUUID
316             MD5
317             SHA1
318             SHA256
319             SHA384
320             SHA512
321             COALESCE
322             IF
323             STRLANG
324             STRDT
325             sameTerm
326             isIRI
327             isURI
328             isBLANK
329             isLITERAL
330             isNUMERIC
331             REGEX
332             SUBSTR
333             REPLACE
334             NOT__EXISTS
335             EXISTS
336             );
337              
338             our @sparqlAggregate = qw(
339             COUNT
340             SUM
341             MIN
342             MAX
343             AVG
344             SAMPLE
345             GROUP_CONCAT
346             );
347              
348             our @sparqlOrdering = qw(
349             ASC
350             DESC
351             );
352              
353             our %pretdslKeywords = (
354             label => "http://www.w3.org/2000/01/rdf-schema#label",
355             comment => "http://www.w3.org/2000/01/rdf-schema#comment",
356             seealso => "http://www.w3.org/2000/01/rdf-schema#seeAlso",
357             abstract_from => "http://purl.org/NET/cpan-uri/terms#abstract_from",
358             author_from => "http://purl.org/NET/cpan-uri/terms#author_from",
359             license_from => "http://purl.org/NET/cpan-uri/terms#license_from",
360             requires_from => "http://purl.org/NET/cpan-uri/terms#requires_from",
361             perl_version_from => "http://purl.org/NET/cpan-uri/terms#perl_version_from",
362             version_from => "http://purl.org/NET/cpan-uri/terms#version_from",
363             readme_from => "http://purl.org/NET/cpan-uri/terms#readme_from",
364             no_index => "http://purl.org/NET/cpan-uri/terms#no_index",
365             install_script => "http://purl.org/NET/cpan-uri/terms#install_script",
366             requires => "http://purl.org/NET/cpan-uri/terms#requires",
367             requires_external_bin => "http://purl.org/NET/cpan-uri/terms#requires_external_bin",
368             recommends => "http://purl.org/NET/cpan-uri/terms#recommends",
369             test_requires => "http://purl.org/NET/cpan-uri/terms#test_requires",
370             configure_requires => "http://purl.org/NET/cpan-uri/terms#configure_requires",
371             build_requires => "http://purl.org/NET/cpan-uri/terms#build_requires",
372             provides => "http://purl.org/NET/cpan-uri/terms#provides",
373             issued => "http://purl.org/NET/dc/terms/issued",
374             changeset => "http://ontologi.es/doap-changeset#changeset",
375             item => "http://ontologi.es/doap-changeset#item",
376             versus => "http://ontologi.es/doap-changeset#versus",
377             Addition => "http://ontologi.es/pretdsl#dt/Addition",
378             Bugfix => "http://ontologi.es/pretdsl#dt/Bugfix",
379             Change => "http://ontologi.es/pretdsl#dt/Change",
380             Documentation => "http://ontologi.es/pretdsl#dt/Documentation",
381             Packaging => "http://ontologi.es/pretdsl#dt/Packaging",
382             Regresion => "http://ontologi.es/pretdsl#dt/Regression",
383             Removal => "http://ontologi.es/pretdsl#dt/Removal",
384             SecurityFix => "http://ontologi.es/pretdsl#dt/SecurityFix",
385             SecurityRegression => "http://ontologi.es/pretdsl#dt/SecurityRegression",
386             Update => "http://ontologi.es/pretdsl#dt/Update",
387             );
388              
389             sub _peek
390             {
391 863     863   1087 my $self = shift;
392 863         1000 my ($regexp) = @_;
393 863 100       6123 $regexp = qr{^(\Q$regexp\E)} unless ref $regexp;
394            
395 863 100       1110 if (my @m = (${$self->_remaining} =~ $regexp))
  863         4254  
396             {
397 78         394 return \@m;
398             }
399            
400 785         5703 return;
401             }
402              
403             sub _pull_token
404             {
405 78     78   13936 my $self = shift;
406 78         207 my ($spelling, $class, %more) = @_;
407 78 50       174 defined $spelling or WTF->throw("Tried to pull undef token!");
408 78         88 substr(${$self->_remaining}, 0, length $spelling, "");
  78         327  
409 78         141 push @{$self->_tokens}, $class->new(spelling => $spelling, %more);
  78         2119  
410             }
411              
412             sub _pull_bnode
413             {
414 0     0   0 my $self = shift;
415 0 0       0 ${$self->_remaining} =~ m/^(_:[$nameStartChar][$nameChar]*)/
  0         0  
416             ? $self->_pull_token($1, BNode)
417             : $self->_pull("_:", BNode)
418             }
419              
420             sub _pull_variable
421             {
422 0     0   0 my $self = shift;
423 0         0 ${$self->_remaining} =~ m/^([\?\$][$nameStartChar][$nameChar]*)/
  0         0  
424             ? $self->_pull_token($1, Variable)
425 0 0       0 : $self->_pull(substr(${$self->_remaining}, 0, 1), Variable)
426             }
427              
428             sub _pull_whitespace
429             {
430 35     35   53 my $self = shift;
431 35         257 $self->_pull_token($1, Whitespace)
432 35 50       43 if ${$self->_remaining} =~ m/^(\s*)/sm;
433             }
434              
435             sub _pull_uri
436             {
437 7     7   10 my $self = shift;
438 7         94 return $self->_pull_token($1, URIRef)
439 7 50       11 if ${$self->_remaining} =~ m/^(<(?:\\\\|\\.|[^<>\\]){0,1024}>)/;
440 0         0 $self->_pull_token("<", Unknown);
441             }
442              
443             sub _pull_curie
444             {
445 9     9   17 my $self = shift;
446 9         347 return $self->_pull_token($1, CURIE)
447 9 50       12 if ${$self->_remaining} =~ m/^(([$nameStartChar2][$nameChar]*)?:([$nameStartChar2][$nameChar]*)?)/;
448 0         0 $self->_pull_token(substr(${$self->_remaining}, 0, 1), Unknown);
  0         0  
449             }
450              
451             # Same rules as RDF::TrineX::Parser::Pretdsl
452             sub _pull_pretdsl
453             {
454 2     2   3 my $self = shift;
455 2         4 my ($spelling) = @_;
456            
457 2 50       9 $spelling =~ /^d/ and return $self->_pull_token($spelling, Pretdsl_Perl_Dist);
458 2 50       9 $spelling =~ /^r/ and return $self->_pull_token($spelling, Pretdsl_Perl_Release);
459 2 50       7 $spelling =~ /^m/ and return $self->_pull_token($spelling, Pretdsl_Perl_Module);
460 2 50       6 $spelling =~ /^f/ and return $self->_pull_token($spelling, Pretdsl_Perl_File);
461 2 50       8 $spelling =~ /^p/ and return $self->_pull_token($spelling, Pretdsl_Perl_Package);
462            
463 2         13 my ($x, $v) = split /\s+/, substr($spelling, 1, length($spelling)-2);
464 2 50       9 $spelling =~ m{::} and return $self->_pull_token($spelling, Pretdsl_Perl_Module);
465 2 50       8 $spelling =~ m{/} and return $self->_pull_token($spelling, Pretdsl_Perl_File);
466 2 100       9 length($v) and return $self->_pull_token($spelling, Pretdsl_Perl_Release);
467            
468 1         6 return $self->_pull_token($spelling, Pretdsl_Perl_Dist);
469             }
470              
471             # XXX - this is probably too naive
472             sub _pull_shortstring
473             {
474 2     2   3 my $self = shift;
475 2         4 my $quote_char = substr(${$self->_remaining}, 0, 1);
  2         19  
476 2         61 $self->_pull_token($1, ShortString, quote_char => $quote_char)
477 2 50       5 if ${$self->_remaining} =~ m/^($quote_char(?:\\\\|\\.|[^$quote_char])*?$quote_char)/;
478             }
479              
480             # XXX - this is probably too naive
481             sub _pull_longstring
482             {
483 0     0   0 my $self = shift;
484 0         0 my $quote_char = substr(${$self->_remaining}, 0, 1);
  0         0  
485 0         0 $self->_pull_token($1, LongString, quote_char => $quote_char)
486 0 0       0 if ${$self->_remaining} =~ m/^($quote_char{3}.*?$quote_char{3})/ms;
487             }
488              
489             sub _scalarref
490             {
491 2     2   4 my $self = shift;
492 2         4 my ($thing) = @_;
493            
494 2 0 33     17 if (blessed $thing and $thing->isa("RDF::Trine::Model") and $self->can("_serializer"))
      33        
495             {
496 0         0 my $t = $self->_serializer->new->serialize_model_to_string($thing);
497 0         0 $thing = \$t
498             }
499            
500 2 0 33     16 if (blessed $thing and $thing->isa("RDF::Trine::Iterator") and $self->can("_serializer"))
      33        
501             {
502 0         0 my $t = $self->_serializer->new->serialize_iterator_to_string($thing);
503 0         0 $thing = \$t
504             }
505            
506 2 50       9 unless (ref $thing eq 'SCALAR')
507             {
508 0         0 my $fh = as_filehandle($thing);
509 0         0 local $/;
510 0         0 my $t = <$fh>;
511 0         0 $thing = \$t;
512             }
513            
514 2         24 return $thing;
515             }
516              
517             sub tokenize
518             {
519 2     2 1 5 my $self = shift;
520 2 50       8 ref $self or WrongInvocant->throw("this is an object method!");
521            
522 2         17 $self->_remaining( $self->_scalarref(@_) );
523 2         14 $self->_tokens([]);
524            
525             # Calculate these each time in case somebody wants to play with
526             # our variables!
527             my $_regexify = sub
528             {
529 12     12   67 my @in = @_;
530 12         154 my $joined = join "|", map { s/__/\\s+/g; $_ } map quotemeta, @in;
  306         394  
  306         517  
531 12         2342 qr{^($joined)}i;
532 2         15 };
533 2         11 my $sparqlKeyword = $_regexify->(@sparqlQueryWord, @sparqlUpdateWord);
534 2         32 my $sparqlFunction = $_regexify->(@sparqlFunction);
535 2         35 my $sparqlAggregate = $_regexify->(@sparqlAggregate);
536 2         12 my $sparqlOrdering = $_regexify->(@sparqlOrdering);
537 2         9 my $sparqlOperator = $_regexify->(@sparqlOperator);
538 2         36 my $pretdslKeyword = $_regexify->(sort { length $a <=> length $b } keys %pretdslKeywords);
  264         263  
539            
540             # Don't need to repeatedly call this method!
541 2         45 my $IS_NTRIPLES = ($self->mode & MODE_NTRIPLES);
542 2   0     17 my $IS_TURTLE = ($self->mode & MODE_TURTLE or $self->mode & MODE_TRIG or $self->mode & MODE_NOTATION_3 or $self->mode & MODE_PRETDSL);
543 2   66     15 my $IS_NOTATION_3 = ($self->mode & MODE_NOTATION_3 or $self->mode & MODE_PRETDSL);
544 2         8 my $IS_SPARQL = ($self->mode & MODE_SPARQL);
545 2         6 my $IS_PRETDSL = ($self->mode & MODE_PRETDSL);
546 2         8 my $IS_TRIG = ($self->mode & MODE_TRIG);
547 2   0     10 my $ABOVE_NTRIPLES = ($IS_TURTLE or $IS_NOTATION_3 or $IS_SPARQL or $IS_PRETDSL or $IS_TRIG);
548            
549             # Declare this ahead of time for use in the big elsif!
550 2         4 my $matches;
551            
552 2         4 while (length ${ $self->_remaining })
  80         32320  
553             {
554 78 100 100     207 if ($self->_peek(' ') || $self->_peek("\n") || $self->_peek("\r") || $self->_peek("\t"))
    50 66        
    50 66        
    50 66        
    50 66        
    50 66        
    50 66        
    50 33        
    50 33        
    100 33        
    100 33        
    100 66        
    50 66        
    50 33        
    50 66        
    50 66        
    100 66        
    100 100        
    50 100        
    100 66        
    100 100        
    50 100        
    100 66        
    50 33        
    50 33        
    50 33        
    50 33        
    50 33        
    100 66        
    100 66        
    50 66        
    50 33        
    50 33        
    50 33        
    50 33        
    50 33        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0          
    0          
555             {
556 35         90 $self->_pull_whitespace;
557             }
558             elsif ($IS_NOTATION_3||$IS_SPARQL||$IS_TRIG and $self->_peek('{'))
559             {
560 0         0 $self->_pull_token('{', Brace);
561             }
562             elsif ($IS_NOTATION_3||$IS_SPARQL||$IS_TRIG and $self->_peek('}'))
563             {
564 0         0 $self->_pull_token('}', Brace);
565             }
566             elsif ($ABOVE_NTRIPLES and $self->_peek('['))
567             {
568 0         0 $self->_pull_token('[', Bracket);
569             }
570             elsif ($ABOVE_NTRIPLES and $self->_peek(']'))
571             {
572 0         0 $self->_pull_token(']', Bracket);
573             }
574             elsif ($ABOVE_NTRIPLES and $self->_peek('('))
575             {
576 0         0 $self->_pull_token('(', Parenthesis);
577             }
578             elsif ($ABOVE_NTRIPLES and $self->_peek(')'))
579             {
580 0         0 $self->_pull_token(')', Parenthesis);
581             }
582             elsif ($self->_peek('^^'))
583             {
584 0         0 $self->_pull_token('^^', Datatype);
585             }
586             # Need to handle SPARQL property paths!
587             elsif ($IS_NOTATION_3 and $matches = $self->_peek(qr/^([\!\^])/))
588             {
589 0         0 $self->_pull_token($matches->[0], Path);
590             }
591             elsif ($ABOVE_NTRIPLES and $matches = $self->_peek(qr/^([\,\;])/))
592             {
593 3         16 $self->_pull_token($matches->[0], Punctuation);
594             }
595             elsif ($self->_peek('.'))
596             {
597 9         46 $self->_pull_token('.', Punctuation);
598             }
599             elsif ($IS_NOTATION_3||$IS_TURTLE||$IS_TRIG and $matches = $self->_peek(qr/^(\@(?:prefix|base))/))
600             {
601 6         29 $self->_pull_token($matches->[0], AtRule);
602             }
603             elsif ($IS_NOTATION_3 and $matches = $self->_peek(qr/^(\@(?:keywords|forSome|forAll))/))
604             {
605 0         0 $self->_pull_token($matches->[0], AtRule);
606             }
607             elsif ($matches = $self->_peek(qr/^(\@[a-z0-9-]+)/i))
608             {
609 0         0 $self->_pull_token($matches->[0], Language);
610             }
611             elsif ($matches = $self->_peek(qr/^(#.*?)(?:\r|\n|$)/is))
612             {
613 0         0 $self->_pull_token($matches->[0], Comment);
614             }
615             elsif ($IS_PRETDSL and $matches = $self->_peek(qr{^(RT#[0-9]+)}i))
616             {
617 0         0 $self->_pull_token($matches->[0], Pretdsl_RT);
618             }
619             elsif ($IS_PRETDSL and $matches = $self->_peek(qr{^(cpan:\w+)}i))
620             {
621 1         8 $self->_pull_token($matches->[0], Pretdsl_CPANID);
622             }
623             elsif ($IS_PRETDSL and $matches = $self->_peek(qr{^([drfmp]?`.*?`)}i))
624             {
625 2         21 $self->_pull_pretdsl($matches->[0]);
626             }
627             elsif ($IS_PRETDSL and $matches = $self->_peek(qr{^([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{4}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})?)}i))
628             {
629 0         0 $self->_pull_token($matches->[0], Pretdsl_DateTime);
630             }
631             elsif ($IS_PRETDSL and $matches = $self->_peek(qr{^([0-9]{4}-[0-9]{2}-[0-9]{2})}i))
632             {
633 1         5 $self->_pull_token($matches->[0], Pretdsl_Date);
634             }
635             elsif ($IS_PRETDSL and $matches = $self->_peek($pretdslKeyword))
636             {
637 2         12 $self->_pull_token($matches->[0], Pretdsl_Keyword, absolute_uri => $pretdslKeywords{$matches->[0]});
638             }
639             elsif ($self->_peek('_:'))
640             {
641 0         0 $self->_pull_bnode;
642             }
643             elsif ($ABOVE_NTRIPLES and $matches = $self->_peek(qr/^([$nameStartChar2][$nameChar]*)?:([$nameStartChar2][$nameChar]*)?/))
644             {
645 9         42 $self->_pull_curie;
646             }
647             elsif ($ABOVE_NTRIPLES and $matches = $self->_peek(qr/^([\-\+]?([0-9]+\.[0-9]*e[\-\+]?[0-9]+))/i))
648             {
649 0         0 $self->_pull_token($matches->[0], Number_Double);
650             }
651             elsif ($ABOVE_NTRIPLES and $matches = $self->_peek(qr/^([\-\+]?(\.[0-9]+e[\-\+]?[0-9]+))/i))
652             {
653 0         0 $self->_pull_token($matches->[0], Number_Double);
654             }
655             elsif ($ABOVE_NTRIPLES and $matches = $self->_peek(qr/^([\-\+]?([0-9]+e[\-\+]?[0-9]+))/i))
656             {
657 0         0 $self->_pull_token($matches->[0], Number_Double);
658             }
659             elsif ($ABOVE_NTRIPLES and $matches = $self->_peek(qr/^([\-\+]?([0-9]+\.[0-9]*))/))
660             {
661 0         0 $self->_pull_token($matches->[0], Number_Decimal);
662             }
663             elsif ($ABOVE_NTRIPLES and $matches = $self->_peek(qr/^([\-\+]?(\.[0-9]+))/))
664             {
665 0         0 $self->_pull_token($matches->[0], Number_Decimal);
666             }
667             elsif ($ABOVE_NTRIPLES and $matches = $self->_peek(qr/^([\-\+]?([0-9]+))/))
668             {
669 1         6 $self->_pull_token($matches->[0], Number_Integer);
670             }
671             elsif ($self->_peek('<'))
672             {
673 7         30 $self->_pull_uri;
674             }
675             elsif ($IS_NOTATION_3||$IS_SPARQL and $self->_peek('?'))
676             {
677 0         0 $self->_pull_variable;
678             }
679             elsif ($IS_SPARQL and $self->_peek('$'))
680             {
681 0         0 $self->_pull_variable;
682             }
683             elsif ($IS_SPARQL and $self->_peek('*'))
684             {
685 0         0 $self->_pull_token('*', Variable);
686             }
687             elsif ($ABOVE_NTRIPLES and $self->_peek('"""') || $self->_peek("'''"))
688             {
689 0         0 $self->_pull_longstring;
690             }
691             elsif ($ABOVE_NTRIPLES and $self->_peek("'"))
692             {
693 0         0 $self->_pull_shortstring;
694             }
695             elsif ($self->_peek('"'))
696             {
697 2         26 $self->_pull_shortstring;
698             }
699             elsif ($IS_SPARQL and $matches = $self->_peek($sparqlKeyword))
700             {
701 0         0 $self->_pull_token($matches->[0], Sparql_Keyword);
702             }
703             elsif ($IS_SPARQL and $matches = $self->_peek($sparqlFunction))
704             {
705 0         0 $self->_pull_token($matches->[0], Sparql_Function);
706             }
707             elsif ($IS_SPARQL and $matches = $self->_peek($sparqlAggregate))
708             {
709 0         0 $self->_pull_token($matches->[0], Sparql_Aggregate);
710             }
711             elsif ($IS_SPARQL and $matches = $self->_peek($sparqlOrdering))
712             {
713 0         0 $self->_pull_token($matches->[0], Sparql_Ordering);
714             }
715             elsif ($IS_SPARQL and $matches = $self->_peek($sparqlOperator))
716             {
717 0         0 $self->_pull_token($matches->[0], Sparql_Operator);
718             }
719             elsif ($ABOVE_NTRIPLES and $matches = $self->_peek(qr/^(true|false)\b/i))
720             {
721 0         0 $self->_pull_token($matches->[0], Boolean);
722             }
723             elsif ($ABOVE_NTRIPLES and $self->_peek(qr{^(a)\b}))
724             {
725 0         0 $self->_pull_token('a', Shorthand);
726             }
727             elsif ($IS_NOTATION_3 and $matches = $self->_peek(qr/^(=|=>|<=)/))
728             {
729 0         0 $self->_pull_token($matches->[0], Shorthand);
730             }
731             elsif ($IS_TRIG and $self->_peek("="))
732             {
733 0         0 $self->_pull_token("=", Shorthand);
734             }
735             elsif ($IS_NOTATION_3 and $matches = $self->_peek(qr/^(is|of)\b/i))
736             {
737 0         0 $self->_pull_token($matches->[0], IsOf);
738             }
739             elsif ($ABOVE_NTRIPLES and $matches = $self->_peek(qr/^([$nameStartChar][$nameChar]*)/))
740             {
741 0         0 $self->_pull_token($matches->[0], Name);
742             }
743             elsif ($matches = $self->_peek(qr/^([^\s\r\n]+)[\s\r\n]/ms))
744             {
745 0         0 $self->_pull_token($matches->[0], Unknown);
746             }
747             elsif ($matches = $self->_peek(qr/^([^\s\r\n]+)$/ms))
748             {
749 0         0 $self->_pull_token($matches->[0], Unknown);
750             }
751             else
752             {
753 0         0 Tokenization->throw(
754             "Could not tokenise string!",
755 0         0 remaining => ${ $self->_remaining },
756             );
757             }
758             }
759            
760 2         95 return $self->_tokens;
761             }
762              
763             sub _fixup
764             {
765 2     2   5 my $self = shift;
766 2         6 my ($base) = @_;
767 2         23 $self->_fixup_urirefs($base);
768 2         18 $self->_fixup_prefix_declarations;
769 2         19 $self->_fixup_curies;
770             }
771              
772             sub _resolve_uri
773             {
774 9     9   20 shift;
775 9         15 my ($relative, $base) = @_;
776 9 100       26 return $relative unless length $base;
777            
778 7         40 require URI;
779            
780             # Where the base itself is relative
781 7 50 66     32 if (!URI->new($relative)->scheme and !URI->new($base)->scheme)
782             {
783             return (
784 0 0       0 $base =~ m{^/}
785             ? "URI"->new_abs(@_)->as_string
786             : substr("URI"->new_abs(@_)->as_string, 1)
787             );
788             }
789            
790 7         4685 "URI"->new_abs(@_)->as_string;
791             }
792              
793             sub _fixup_urirefs
794             {
795 2     2   4 my $self = shift;
796 2         6 my ($base) = @_;
797 2   50     11 $base //= "";
798            
799 2         8 my $tokens = $self->_tokens;
800 2         6 my $i = 0;
801 2         10 while ($i < @$tokens)
802             {
803 76         104 my $t = $tokens->[$i];
804            
805 76 100 66     155 if ($t->isa(URIRef) and not defined $t->absolute_uri)
    100 33        
      100        
      33        
806             {
807 7         971 $t->absolute_uri($self->_resolve_uri($t->uri, $base));
808             }
809             elsif ( ($t->isa(Sparql_Keyword) and lc($t->spelling) eq 'base')
810             or ($t->isa(AtRule) and lc($t->spelling) eq '@base') )
811             {
812             # search ahead for the new base URI
813 2         3215 my $j = 1;
814 2   66     10 while ($tokens->[$i+$j]->isa(Comment) || $tokens->[$i+$j]->isa(Whitespace))
815             {
816 2         1074 $j++;
817 2 50       12 last if !defined $tokens->[$i+$j];
818             }
819 2 50 33     67 if (defined $tokens->[$i+$j] and $tokens->[$i+$j]->can("uri"))
820             {
821             # new base URI found!
822 2         9 $base = $self->_resolve_uri($tokens->[$i+$j]->uri, $base);
823 2         5 $i += ($j - 1);
824             }
825             }
826            
827 76         3527 $i++;
828             }
829             }
830              
831             sub _fixup_prefix_declarations
832             {
833 2     2   4 my $self = shift;
834            
835 2         8 my $tokens = $self->_tokens;
836 2         4 my $i = 0;
837 2         4 my $started;
838             my @bits;
839 2         7 while ($i < @$tokens)
840             {
841 78         98 my $t = $tokens->[$i];
842 78         77 my $is_end;
843            
844 78 100 100     157 if ($t->isa(AtRule) and lc($t->spelling) eq '@prefix')
    50 33        
    100 100        
    100 66        
      100        
      100        
      66        
845             {
846 4         120 $started = $i;
847 4         9 @bits = $t;
848             }
849             elsif ($t->isa(Sparql_Keyword) and lc($t->spelling) eq 'PREFIX')
850             {
851 0         0 $started = $i;
852 0         0 @bits = $t;
853             }
854             elsif (defined $started and $t->isa(CURIE) || $t->isa(URIRef))
855             {
856 14         353 push @bits, $t;
857             }
858             elsif (defined $started and @bits==3 and $t->spelling eq "." and $bits[0]->isa(AtRule))
859             {
860 4         410 $is_end = 1;
861             }
862            
863 78 50 100     2726 if (!$is_end and defined $started and @bits==3 and $bits[0]->isa(Sparql_Keyword))
      100        
      66        
864             {
865 0         0 $is_end = 1;
866             }
867            
868 78 100       275 if ($is_end)
869             {
870 4         12 my $END = PrefixDefinition_End->new;
871 4         2620 my $START = PrefixDefinition_Start->new(
872             prefix => $bits[1]->prefix,
873             absolute_uri => $bits[2]->absolute_uri,
874             end => $END
875             );
876 4         2739 $END->start($START);
877            
878 4         962 $bits[1]->absolute_uri($bits[2]->absolute_uri);
879            
880 4         993 splice(@$tokens, $started, 0, $START); $i++;
  4         9  
881 4         9 splice(@$tokens, $i+1, 0, $END); $i++;
  4         6  
882             }
883            
884 78         190 $i++;
885             }
886             }
887              
888             our %pretdslPrefixes = (
889             "grddl" => "http://www.w3.org/2003/g/data-view#",
890             "ma" => "http://www.w3.org/ns/ma-ont#",
891             "owl" => "http://www.w3.org/2002/07/owl#",
892             "rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
893             "rdfa" => "http://www.w3.org/ns/rdfa#",
894             "rdfs" => "http://www.w3.org/2000/01/rdf-schema#",
895             "rif" => "http://www.w3.org/2007/rif#",
896             "skos" => "http://www.w3.org/2004/02/skos/core#",
897             "skosxl" => "http://www.w3.org/2008/05/skos-xl#",
898             "wdr" => "http://www.w3.org/2007/05/powder#",
899             "void" => "http://rdfs.org/ns/void#",
900             "wdrs" => "http://www.w3.org/2007/05/powder-s#",
901             "xhv" => "http://www.w3.org/1999/xhtml/vocab#",
902             "xml" => "http://www.w3.org/XML/1998/namespace",
903             "xsd" => "http://www.w3.org/2001/XMLSchema#",
904             "cc" => "http://creativecommons.org/ns#",
905             "ctag" => "http://commontag.org/ns#",
906             "dc" => "http://purl.org/dc/terms/",
907             "dcterms" => "http://purl.org/dc/terms/",
908             "foaf" => "http://xmlns.com/foaf/0.1/",
909             "gr" => "http://purl.org/goodrelations/v1#",
910             "ical" => "http://www.w3.org/2002/12/cal/icaltzd#",
911             "og" => "http://ogp.me/ns#",
912             "rev" => "http://purl.org/stuff/rev#",
913             "sioc" => "http://rdfs.org/sioc/ns#",
914             "v" => "http://rdf.data-vocabulary.org/#",
915             "vcard" => "http://www.w3.org/2006/vcard/ns#",
916             "schema" => "http://schema.org/",
917             "cpant" => "http://purl.org/NET/cpan-uri/terms#",
918             "dbug" => "http://ontologi.es/doap-bugs#",
919             "dcs" => "http://ontologi.es/doap-changeset#",
920             "doap" => "http://usefulinc.com/ns/doap#",
921             "earl" => "http://www.w3.org/ns/earl#",
922             "nfo" => "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#",
923             "pretdsl" => "http://ontologi.es/pretdsl#",
924             "pretdsl-dt" => "http://ontologi.es/pretdsl#dt/",
925             );
926              
927             sub _fixup_curies
928             {
929 2     2   5 my $self = shift;
930            
931 2 100       43 my $map = +{
932             $self->mode & MODE_PRETDSL
933             ? %pretdslPrefixes
934             : ()
935             };
936 2         11 my $tokens = $self->_tokens;
937            
938 2         6 for my $t (@$tokens)
939             {
940 86 100 66     3003 if ($t->isa(PrefixDefinition_End))
    100 100        
941             {
942 4         95 $map->{ $t->start->prefix } = $t->start->absolute_uri;
943             }
944             elsif ($t->isa(CURIE) and defined $t->prefix and exists $map->{$t->prefix})
945             {
946 5   50     45 $t->absolute_uri($map->{$t->prefix} . ($t->suffix//""));
947             }
948             }
949             }
950              
951             sub highlight
952             {
953 2     2 1 4291 my $self = shift;
954 2 50       9 ref $self or WrongInvocant->throw("this is an object method!");
955            
956 2         6 my ($text, $base) = @_;
957            
958 2         16 $self->tokenize($text);
959 2         24 $self->_fixup($base);
960            
961 2         38 return join "", map $_->TO_HTML, @{$self->_tokens};
  2         19  
962             }
963              
964             {
965             package Syntax::Highlight::RDF::NTriples;
966             our $AUTHORITY = 'cpan:TOBYINK';
967             our $VERSION = '0.003';
968 1     1   14 use Moo;
  1         2  
  1         22  
969             extends "Syntax::Highlight::RDF";
970 1     1   355 use constant mode => Syntax::Highlight::RDF::MODE_NTRIPLES;
  1         2  
  1         155  
971             sub _serializer
972             {
973 0     0   0 require RDF::Trine::Serializer::NTriples;
974 0         0 "RDF::Trine::Serializer::NTriples";
975             }
976             }
977              
978             {
979             package Syntax::Highlight::RDF::Turtle;
980             our $AUTHORITY = 'cpan:TOBYINK';
981             our $VERSION = '0.003';
982 1     1   5 use Moo;
  1         2  
  1         4  
983             extends "Syntax::Highlight::RDF";
984 1         1403 use constant mode => Syntax::Highlight::RDF::MODE_NTRIPLES
985 1     1   273 | Syntax::Highlight::RDF::MODE_TURTLE;
  1         2  
986             sub _serializer
987             {
988 0 0   0   0 eval { require RDF::TrineX::Serializer::MockTurtleSoup }
  0         0  
989             and return "RDF::TrineX::Serializer::MockTurtleSoup";
990 0         0 require RDF::Trine::Serializer::Turtle;
991 0         0 "RDF::Trine::Serializer::Turtle";
992             }
993             }
994              
995             {
996             package Syntax::Highlight::RDF::Notation_3;
997             our $AUTHORITY = 'cpan:TOBYINK';
998             our $VERSION = '0.003';
999 1     1   16 use Moo;
  1         3  
  1         11  
1000             extends "Syntax::Highlight::RDF";
1001 1         159 use constant mode => Syntax::Highlight::RDF::MODE_NTRIPLES
1002             | Syntax::Highlight::RDF::MODE_TURTLE
1003 1     1   570 | Syntax::Highlight::RDF::MODE_NOTATION_3;
  1         11  
1004             sub _serializer
1005             {
1006 0     0   0 require RDF::Trine::Serializer::Notation3;
1007 0         0 "RDF::Trine::Serializer::Notation3";
1008             }
1009             }
1010              
1011             {
1012             package Syntax::Highlight::RDF::SPARQL_Query;
1013             our $AUTHORITY = 'cpan:TOBYINK';
1014             our $VERSION = '0.003';
1015 1     1   6 use Moo;
  1         3  
  1         4  
1016             extends "Syntax::Highlight::RDF";
1017 1         91 use constant mode => Syntax::Highlight::RDF::MODE_NTRIPLES
1018             | Syntax::Highlight::RDF::MODE_TURTLE
1019 1     1   322 | Syntax::Highlight::RDF::MODE_SPARQL;
  1         15  
1020             }
1021              
1022             {
1023             package Syntax::Highlight::RDF::SPARQL_Update;
1024             our $AUTHORITY = 'cpan:TOBYINK';
1025             our $VERSION = '0.003';
1026 1     1   5 use Moo;
  1         1  
  1         4  
1027             extends "Syntax::Highlight::RDF";
1028 1         94 use constant mode => Syntax::Highlight::RDF::MODE_NTRIPLES
1029             | Syntax::Highlight::RDF::MODE_TURTLE
1030 1     1   300 | Syntax::Highlight::RDF::MODE_SPARQL;
  1         2  
1031             }
1032              
1033             {
1034             package Syntax::Highlight::RDF::Pretdsl;
1035             our $AUTHORITY = 'cpan:TOBYINK';
1036             our $VERSION = '0.003';
1037 1     1   5 use Moo;
  1         2  
  1         4  
1038             extends "Syntax::Highlight::RDF";
1039 1         136 use constant mode => Syntax::Highlight::RDF::MODE_NTRIPLES
1040             | Syntax::Highlight::RDF::MODE_TURTLE
1041             | Syntax::Highlight::RDF::MODE_NOTATION_3
1042 1     1   354 | Syntax::Highlight::RDF::MODE_PRETDSL;
  1         2  
1043             }
1044              
1045             {
1046             package Syntax::Highlight::RDF::NQuads;
1047             our $AUTHORITY = 'cpan:TOBYINK';
1048             our $VERSION = '0.003';
1049 1     1   5 use Moo;
  1         1  
  1         4  
1050             extends "Syntax::Highlight::RDF";
1051 1     1   306 use constant mode => Syntax::Highlight::RDF::MODE_NTRIPLES;
  1         2  
  1         119  
1052             sub _serializer
1053             {
1054 0     0   0 require RDF::Trine::Serializer::NQuads;
1055 0         0 "RDF::Trine::Serializer::NQuads";
1056             }
1057             }
1058              
1059             {
1060             package Syntax::Highlight::RDF::TriG;
1061             our $AUTHORITY = 'cpan:TOBYINK';
1062             our $VERSION = '0.003';
1063 1     1   5 use Moo;
  1         2  
  1         3  
1064             extends "Syntax::Highlight::RDF";
1065 1         710 use constant mode => Syntax::Highlight::RDF::MODE_NTRIPLES
1066             | Syntax::Highlight::RDF::MODE_TURTLE
1067 1     1   341 | Syntax::Highlight::RDF::MODE_TRIG;
  1         1  
1068             }
1069              
1070             sub highlighter
1071             {
1072 4     4 1 3652 my $class = shift;
1073 4 50       21 $class eq __PACKAGE__ or WrongInvocant->throw("this is a factory method!");
1074            
1075 4         9 my ($hint) = @_;
1076            
1077 4 100       23 $hint =~ m{xml}i and do {
1078 1         679 require Syntax::Highlight::XML;
1079 1         9 return "Syntax::Highlight::XML"->new;
1080             };
1081            
1082 3 100       16 $hint =~ m{json}i and do {
1083 1         737 require Syntax::Highlight::JSON2;
1084 1         7 return "Syntax::Highlight::JSON2"->new;
1085             };
1086            
1087 2 100       30 $hint =~ m{(ttl|turtle)}i and return "$class\::Turtle"->new;
1088 1 50       10 $hint =~ m{(nt|n.?triples)}i and return "$class\::NTriples"->new;
1089 1 50       8 $hint =~ m{(nq|n.?quads)}i and return "$class\::NQuads"->new;
1090 1 50       6 $hint =~ m{(trig)}i and return "$class\::TriG"->new;
1091 1 50       9 $hint =~ m{(n3|notation.?3)}i and return "$class\::Notation_3"->new;
1092 1 50       67 $hint =~ m{(pret)}i and return "$class\::Pretdsl"->new;
1093 0 0         $hint =~ m{(sparql.?update)}i and return "$class\::SPARQL_Update"->new;
1094 0 0         $hint =~ m{(sparql)}i and return "$class\::SPARQL_Query"->new;
1095 0 0         $hint =~ m{(text/plain)}i and return "$class\::NTriples"->new;
1096            
1097 0           return $class->new;
1098             }
1099              
1100             1;
1101              
1102             __END__
1103              
1104             =pod
1105              
1106             =encoding utf-8
1107              
1108             =head1 NAME
1109              
1110             Syntax::Highlight::RDF - syntax highlighting for various RDF-related formats
1111              
1112             =head1 SYNOPSIS
1113              
1114             use Syntax::Highlight::RDF;
1115             my $syntax = "Syntax::Highlight::RDF"->highlighter("Turtle");
1116             print $syntax->highlight($filehandle);
1117              
1118             =head1 DESCRIPTION
1119              
1120             Outputs pretty syntax-highlighted HTML for RDF-related formats. (Actually just
1121             adds C<< <span> >> elements with C<< class >> attributes. You're expected to
1122             bring your own CSS.)
1123              
1124             =head2 Formats
1125              
1126             =over
1127              
1128             =item *
1129              
1130             N-Triples
1131              
1132             =item *
1133              
1134             N-Quads
1135              
1136             =item *
1137              
1138             Turtle
1139              
1140             =item *
1141              
1142             TriG
1143              
1144             =item *
1145              
1146             Notation 3
1147              
1148             =item *
1149              
1150             Pretdsl
1151              
1152             =item *
1153              
1154             SPARQL Query 1.1 (but not property paths yet)
1155              
1156             =item *
1157              
1158             SPARQL Update 1.1 (but not property paths yet)
1159              
1160             =item *
1161              
1162             JSON - intended for RDF/JSON and SPARQL Results JSON, but just generic highlighting
1163              
1164             =item *
1165              
1166             XML - intended for RDF/XML and SPARQL Results XML, but just generic highlighting
1167              
1168             =back
1169              
1170             =head2 Methods
1171              
1172             =over
1173              
1174             =item C<< highlighter($format) >>
1175              
1176             Factory method; generally preferred over calling C<new> on a specific
1177             class.
1178              
1179             "Syntax::Highlight::RDF"->highlighter("Turtle");
1180             "Syntax::Highlight::RDF::Turtle"->new; # avoid!
1181              
1182             =item C<< highlight($input, $base) >>
1183              
1184             Highlight some RDF.
1185              
1186             C<< $input >> may be a file handle, filename or a scalar ref of text.
1187             (Most highlighters will also attempt to Do What You Mean if passed something
1188             else sane like an RDF::Trine::Model.) C<< $base >> is an optional base for
1189             resolving relative URIs.
1190              
1191             Returns a string of HTML.
1192              
1193             =item C<< tokenize($input) >>
1194              
1195             This is mostly intended for subclassing Syntax::Highlight::RDF.
1196              
1197             C<< $input >> may be a file handle, filename or a scalar ref of text.
1198              
1199             Returns an arrayref of token objects. The exact API for the token objects
1200             is subject to change, but currently they support C<< TYPE >> and
1201             C<< spelling >> methods.
1202              
1203             =back
1204              
1205             =begin private
1206              
1207             =item MODE_NTRIPLES => 0,
1208              
1209             =item MODE_TURTLE => 1,
1210              
1211             =item MODE_NOTATION_3 => 2,
1212              
1213             =item MODE_SPARQL => 4,
1214              
1215             =item MODE_PRETDSL => 8,
1216              
1217             =item MODE_TRIG => 16,
1218              
1219             =item mode
1220              
1221             =end private
1222              
1223             =head1 BUGS
1224              
1225             Please report any bugs to
1226             L<http://rt.cpan.org/Dist/Display.html?Queue=Syntax-Highlight-RDF>.
1227              
1228             =head1 SEE ALSO
1229              
1230             L<Syntax::Highlight::JSON2>,
1231             L<Syntax::Highlight::XML>.
1232              
1233             L<PPI::HTML>,
1234             L<Syntax::Highlight::Engine::Kate>.
1235              
1236             L<RDF::Trine>, L<RDF::Query>.
1237              
1238             L<http://www.perlrdf.org/>.
1239              
1240             =head1 AUTHOR
1241              
1242             Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
1243              
1244             =head1 COPYRIGHT AND LICENCE
1245              
1246             This software is copyright (c) 2013 by Toby Inkster.
1247              
1248             This is free software; you can redistribute it and/or modify it under
1249             the same terms as the Perl 5 programming language system itself.
1250              
1251             =head1 DISCLAIMER OF WARRANTIES
1252              
1253             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
1254             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1255             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1256