| blib/lib/Text/Amuse/InlineElement.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 169 | 181 | 93.3 |
| branch | 83 | 100 | 83.0 |
| condition | 5 | 6 | 83.3 |
| subroutine | 22 | 23 | 95.6 |
| pod | 15 | 15 | 100.0 |
| total | 294 | 325 | 90.4 |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | package Text::Amuse::InlineElement; | ||||||
| 2 | 44 | 44 | 332 | use strict; | |||
| 44 | 114 | ||||||
| 44 | 1273 | ||||||
| 3 | 44 | 44 | 235 | use warnings; | |||
| 44 | 100 | ||||||
| 44 | 1103 | ||||||
| 4 | 44 | 44 | 250 | use utf8; | |||
| 44 | 106 | ||||||
| 44 | 231 | ||||||
| 5 | 44 | 44 | 1535 | use Text::Amuse::Utils; | |||
| 44 | 93 | ||||||
| 44 | 122939 | ||||||
| 6 | |||||||
| 7 | =head1 NAME | ||||||
| 8 | |||||||
| 9 | Text::Amuse::InlineElement - Helper for Text::Amuse | ||||||
| 10 | |||||||
| 11 | =head1 METHODS | ||||||
| 12 | |||||||
| 13 | Everything here is pretty much internal only, underdocumented and | ||||||
| 14 | subject to change. | ||||||
| 15 | |||||||
| 16 | =head2 new(%args) | ||||||
| 17 | |||||||
| 18 | Constructor. Accepts the following named arguments (which are also | ||||||
| 19 | accessors) | ||||||
| 20 | |||||||
| 21 | =over 4 | ||||||
| 22 | |||||||
| 23 | =item type | ||||||
| 24 | |||||||
| 25 | The element type | ||||||
| 26 | |||||||
| 27 | =item string | ||||||
| 28 | |||||||
| 29 | The raw string | ||||||
| 30 | |||||||
| 31 | =item last_position | ||||||
| 32 | |||||||
| 33 | The offset of the last character in the parsed string | ||||||
| 34 | |||||||
| 35 | =item tag | ||||||
| 36 | |||||||
| 37 | The name of the tag | ||||||
| 38 | |||||||
| 39 | =item fmt | ||||||
| 40 | |||||||
| 41 | C |
||||||
| 42 | |||||||
| 43 | =cut | ||||||
| 44 | |||||||
| 45 | sub new { | ||||||
| 46 | 36431 | 36431 | 1 | 132251 | my ($class, %args) = @_; | ||
| 47 | 36431 | 125476 | my $self = { | ||||
| 48 | type => '', | ||||||
| 49 | string => '', | ||||||
| 50 | last_position => 0, | ||||||
| 51 | tag => '', | ||||||
| 52 | fmt => '', | ||||||
| 53 | lang => 'en', | ||||||
| 54 | }; | ||||||
| 55 | 36431 | 122652 | foreach my $k (keys %$self) { | ||||
| 56 | 218586 | 100 | 388524 | if (defined $args{$k}) { | |||
| 57 | 180962 | 269811 | $self->{$k} = $args{$k}; | ||||
| 58 | } | ||||||
| 59 | 218586 | 333227 | delete $args{$k}; | ||||
| 60 | } | ||||||
| 61 | 36431 | 50 | 80106 | die "Extra arguments passed :" . join(" ", %args) if %args; | |||
| 62 | 36431 | 50 | 77217 | die "Missing type for <$self->{string}>" unless $self->{type}; | |||
| 63 | 36431 | 50 | 66 | 105687 | unless ($self->{fmt} eq 'ltx' or $self->{fmt} eq 'html') { | ||
| 64 | 0 | 0 | die "Missing format $self->{fmt} for <$self->{string}>" | ||||
| 65 | } | ||||||
| 66 | 36431 | 264658 | bless $self, $class; | ||||
| 67 | } | ||||||
| 68 | |||||||
| 69 | sub type { | ||||||
| 70 | 390539 | 390539 | 1 | 589958 | my ($self, $type) = @_; | ||
| 71 | 390539 | 100 | 627019 | if ($type) { | |||
| 72 | 2718 | 4485 | $self->{type} = $type; | ||||
| 73 | } | ||||||
| 74 | 390539 | 1008594 | return $self->{type}; | ||||
| 75 | } | ||||||
| 76 | |||||||
| 77 | sub last_position { | ||||||
| 78 | 4555 | 4555 | 1 | 10133 | shift->{last_position}; | ||
| 79 | } | ||||||
| 80 | |||||||
| 81 | sub string { | ||||||
| 82 | 73033 | 73033 | 1 | 205759 | shift->{string}; | ||
| 83 | } | ||||||
| 84 | |||||||
| 85 | =item lang | ||||||
| 86 | |||||||
| 87 | The language code. | ||||||
| 88 | |||||||
| 89 | =cut | ||||||
| 90 | |||||||
| 91 | sub lang { | ||||||
| 92 | 13860 | 13860 | 1 | 30043 | shift->{lang}; | ||
| 93 | } | ||||||
| 94 | |||||||
| 95 | =item append($element) | ||||||
| 96 | |||||||
| 97 | Append the provided string to the self's one and update the | ||||||
| 98 | last_position. | ||||||
| 99 | |||||||
| 100 | =cut | ||||||
| 101 | |||||||
| 102 | sub append { | ||||||
| 103 | 0 | 0 | 1 | 0 | my ($self, $element) = @_; | ||
| 104 | 0 | 0 | $self->{string} .= $element->string; | ||||
| 105 | 0 | 0 | $self->{last_position} = $element->last_position; | ||||
| 106 | } | ||||||
| 107 | |||||||
| 108 | sub tag { | ||||||
| 109 | 35155 | 100 | 35155 | 1 | 63591 | if (@_ > 1) { | |
| 110 | 64 | 116 | $_[0]{tag} = $_[1]; | ||||
| 111 | } | ||||||
| 112 | 35155 | 90586 | $_[0]{tag}; | ||||
| 113 | } | ||||||
| 114 | |||||||
| 115 | sub fmt { | ||||||
| 116 | 51201 | 51201 | 1 | 153916 | shift->{fmt}; | ||
| 117 | } | ||||||
| 118 | |||||||
| 119 | =item stringify | ||||||
| 120 | |||||||
| 121 | Main method to get the desired output from the element. | ||||||
| 122 | |||||||
| 123 | =cut | ||||||
| 124 | |||||||
| 125 | sub stringify { | ||||||
| 126 | 31852 | 31852 | 1 | 47242 | my $self = shift; | ||
| 127 | 31852 | 52190 | my $type = $self->type; | ||||
| 128 | 31852 | 60063 | my $string = $self->string; | ||||
| 129 | 31852 | 100 | 66819 | if ($type eq 'text') { | |||
| 130 | 24796 | 100 | 46595 | if ($self->is_latex) { | |||
| 50 | |||||||
| 131 | 10936 | 21065 | $string = $self->escape_tex($string); | ||||
| 132 | 10936 | 22383 | $string = $self->_ltx_replace_ldots($string); | ||||
| 133 | 10936 | 19507 | $string = $self->_ltx_replace_slash($string); | ||||
| 134 | 10936 | 56424 | return $string; | ||||
| 135 | } | ||||||
| 136 | elsif ($self->is_html) { | ||||||
| 137 | 13860 | 100 | 24695 | if ($self->lang eq 'fr') { | |||
| 138 | 41 | 97 | $string = $self->_html_french_punctuation($string); | ||||
| 139 | 41 | 94 | $string = $self->escape_all_html($string); | ||||
| 140 | 41 | 112 | $string =~ s/\x{a0}/ /g; # make them visible | ||||
| 141 | 41 | 105 | $string =~ s/\x{202f}/ /g; # ditto | ||||
| 142 | 41 | 236 | return $string; | ||||
| 143 | } | ||||||
| 144 | else { | ||||||
| 145 | 13819 | 26403 | return $self->escape_all_html($string); | ||||
| 146 | } | ||||||
| 147 | } | ||||||
| 148 | else { | ||||||
| 149 | 0 | 0 | die "Not reached"; | ||||
| 150 | } | ||||||
| 151 | } | ||||||
| 152 | 7056 | 100 | 15355 | if ($type eq 'safe') { | |||
| 153 | 1617 | 3831 | return $self->verbatim_string($string); | ||||
| 154 | } | ||||||
| 155 | 5439 | 100 | 11314 | if ($type eq 'ruby') { | |||
| 156 | 19 | 50 | 154 | if ($string =~ m/\A\s*(.+?)\s*\|\s*(.+?)\s*<\/ruby>\z/) { | |||
| 157 | 19 | 78 | my ($main, $ann) = ($1, $2); | ||||
| 158 | 19 | 61 | $main = $self->verbatim_string($main); | ||||
| 159 | 19 | 46 | $ann = $self->verbatim_string($ann); | ||||
| 160 | 19 | 100 | 42 | if ($self->is_latex) { | |||
| 50 | |||||||
| 161 | 9 | 101 | return sprintf("\\ruby{%s}{%s}", $main, $ann); | ||||
| 162 | } | ||||||
| 163 | elsif ($self->is_html) { | ||||||
| 164 | 10 | 137 | return sprintf(" |
||||
| 165 | } | ||||||
| 166 | } | ||||||
| 167 | } | ||||||
| 168 | 5420 | 100 | 100 | 26140 | if ($type eq 'verbatim') { | ||
| 100 | |||||||
| 100 | |||||||
| 100 | |||||||
| 100 | |||||||
| 100 | |||||||
| 100 | |||||||
| 50 | |||||||
| 169 | 548 | 50 | 3227 | if ($string =~ /\A |
|||
| 170 | 548 | 1586 | $string = $1; | ||||
| 171 | 548 | 1299 | return $self->verbatim_string($string); | ||||
| 172 | } | ||||||
| 173 | else { | ||||||
| 174 | 0 | 0 | die "<$string> doesn't match verbatim!"; | ||||
| 175 | } | ||||||
| 176 | } | ||||||
| 177 | elsif ($type eq 'anchor') { | ||||||
| 178 | 812 | 1344 | my $anchor = $string; | ||||
| 179 | 812 | 2091 | $anchor =~ s/[^A-Za-z0-9-]//g; | ||||
| 180 | 812 | 50 | 2198 | die "Bad anchor " . $string unless length($anchor); | |||
| 181 | 812 | 100 | 1757 | if ($self->is_latex) { | |||
| 50 | |||||||
| 182 | 371 | 1319 | my $label = <<"TEX"; | ||||
| 183 | \\hyperdef{amuse}{$anchor}{}% | ||||||
| 184 | \\label{textamuse:$anchor}% | ||||||
| 185 | TEX | ||||||
| 186 | 371 | 2350 | return $label; | ||||
| 187 | } | ||||||
| 188 | elsif ($self->is_html) { | ||||||
| 189 | 441 | 3425 | return qq{<\/a>\n} | ||||
| 190 | } | ||||||
| 191 | else { | ||||||
| 192 | 0 | 0 | die "Not reached"; | ||||
| 193 | } | ||||||
| 194 | } | ||||||
| 195 | elsif ($type eq 'open' or $type eq 'close') { | ||||||
| 196 | 2522 | 100 | 4676 | if ($self->tag =~ m/\A\[([a-zA-Z-]+)\]\z/) { | |||
| 197 | 44 | 127 | my $iso = $1; | ||||
| 198 | 44 | 100 | 104 | if ($self->is_latex) { | |||
| 50 | |||||||
| 199 | 22 | 100 | 57 | if ($type eq 'open') { | |||
| 200 | 11 | 40 | my $lang = Text::Amuse::Utils::get_latex_lang($iso); | ||||
| 201 | 11 | 101 | return "\\foreignlanguage{$lang}{"; | ||||
| 202 | } | ||||||
| 203 | else { | ||||||
| 204 | 11 | 57 | return "}"; | ||||
| 205 | } | ||||||
| 206 | } | ||||||
| 207 | elsif ($self->is_html) { | ||||||
| 208 | 22 | 100 | 60 | if ($type eq 'open') { | |||
| 209 | 11 | 77 | return qq{}; | ||||
| 210 | } | ||||||
| 211 | else { | ||||||
| 212 | 11 | 62 | return ""; | ||||
| 213 | } | ||||||
| 214 | } | ||||||
| 215 | } | ||||||
| 216 | 2478 | 5006 | my $out = $self->_markup_table->{$self->tag}->{$type}->{$self->fmt}; | ||||
| 217 | 2478 | 50 | 23212 | die "Missing markup for $self->fmt $type $self->tag" unless $out; | |||
| 218 | 2478 | 11925 | return $out; | ||||
| 219 | } | ||||||
| 220 | elsif ($type eq 'nobreakspace') { | ||||||
| 221 | 90 | 100 | 204 | if ($self->is_latex) { | |||
| 50 | |||||||
| 222 | 45 | 198 | return '~'; | ||||
| 223 | } | ||||||
| 224 | elsif ($self->is_html) { | ||||||
| 225 | 45 | 216 | return ' ' | ||||
| 226 | } | ||||||
| 227 | } | ||||||
| 228 | elsif ($type eq 'noindent') { | ||||||
| 229 | 32 | 100 | 88 | if ($self->is_latex) { | |||
| 230 | 13 | 70 | return "\\noindent "; | ||||
| 231 | } | ||||||
| 232 | else { | ||||||
| 233 | 19 | 38 | my $leading = ''; | ||||
| 234 | 19 | 50 | 90 | if ($string =~ m/\A(\s+)/) { | |||
| 235 | 0 | 0 | $leading = $1; | ||||
| 236 | } | ||||||
| 237 | 19 | 125 | return "$leading "; |
||||
| 238 | } | ||||||
| 239 | } | ||||||
| 240 | elsif ($type eq 'br') { | ||||||
| 241 | 541 | 100 | 1125 | if ($self->is_latex) { | |||
| 242 | 240 | 1100 | return "\\forcelinebreak "; | ||||
| 243 | } | ||||||
| 244 | else { | ||||||
| 245 | 301 | 544 | my $leading = ''; | ||||
| 246 | 301 | 100 | 1129 | if ($string =~ m/\A(\s+)/) { | |||
| 247 | 83 | 222 | $leading = $1; | ||||
| 248 | } | ||||||
| 249 | 301 | 1592 | return "$leading "; |
||||
| 250 | } | ||||||
| 251 | } | ||||||
| 252 | elsif ($type eq 'bigskip') { | ||||||
| 253 | 88 | 100 | 289 | if ($self->is_latex) { | |||
| 254 | 44 | 257 | return "\n\\bigskip"; | ||||
| 255 | } | ||||||
| 256 | else { | ||||||
| 257 | 44 | 100 | my $leading = ''; | ||||
| 258 | 44 | 100 | 221 | if ($string =~ m/\A(\s+)/) { | |||
| 259 | 1 | 4 | $leading = $1; | ||||
| 260 | } | ||||||
| 261 | 44 | 280 | return "$leading "; |
||||
| 262 | } | ||||||
| 263 | } | ||||||
| 264 | elsif ($type eq 'verbatim_code') { | ||||||
| 265 | # remove the prefixes | ||||||
| 266 | 787 | 100 | 4931 | warn qq{ is already verbatim! in "$string"\n} if $string =~ m{ |
|||
| 267 | 787 | 100 | 4914 | if ($string =~ /\A=(.+)=\z/s) { | |||
| 100 | |||||||
| 50 | |||||||
| 268 | 628 | 1927 | $string = $1; | ||||
| 269 | } | ||||||
| 270 | elsif ($string =~ /\A |
||||||
| 271 | 50 | 199 | $string = $1; | ||||
| 272 | } | ||||||
| 273 | elsif ($string =~ /\A(.*)<\/code>\z/s) { |
||||||
| 274 | 109 | 356 | $string = $1; | ||||
| 275 | } | ||||||
| 276 | else { | ||||||
| 277 | 0 | 0 | die "$string doesn't match the pattern!"; |
||||
| 278 | } | ||||||
| 279 | 787 | 100 | 2154 | if (length $string) { | |||
| 280 | return $self->_markup_table->{code}->{open}->{$self->fmt} | ||||||
| 281 | . $self->verbatim_string($string) | ||||||
| 282 | 769 | 1895 | . $self->_markup_table->{code}->{close}->{$self->fmt}; | ||||
| 283 | } | ||||||
| 284 | else { | ||||||
| 285 | 18 | 93 | return ''; | ||||
| 286 | } | ||||||
| 287 | } | ||||||
| 288 | else { | ||||||
| 289 | 0 | 0 | die "Unrecognized type " . $type . " for " . $string; | ||||
| 290 | } | ||||||
| 291 | } | ||||||
| 292 | |||||||
| 293 | sub _markup_table { | ||||||
| 294 | return { | ||||||
| 295 | 4016 | 4016 | 103441 | 'rtl' => { | |||
| 296 | open => { | ||||||
| 297 | html => '', | ||||||
| 298 | ltx => "\\RL{", | ||||||
| 299 | }, | ||||||
| 300 | close => { | ||||||
| 301 | html => '', # LRM (U+200E LEFT-TO-RIGHT MARK) | ||||||
| 302 | ltx => '}', | ||||||
| 303 | }, | ||||||
| 304 | }, | ||||||
| 305 | 'ltr' => { | ||||||
| 306 | open => { | ||||||
| 307 | html => '', | ||||||
| 308 | ltx => "\\LR{", | ||||||
| 309 | }, | ||||||
| 310 | close => { | ||||||
| 311 | html => '', # RLM (U+200F RIGHT-TO-LEFT MARK) | ||||||
| 312 | ltx => '}', | ||||||
| 313 | }, | ||||||
| 314 | }, | ||||||
| 315 | 'em' => { | ||||||
| 316 | open => { | ||||||
| 317 | html => '', | ||||||
| 318 | ltx => "\\emph{" | ||||||
| 319 | }, | ||||||
| 320 | close => { | ||||||
| 321 | html => '', | ||||||
| 322 | ltx => '}', | ||||||
| 323 | } | ||||||
| 324 | }, | ||||||
| 325 | 'strong' => { | ||||||
| 326 | open => { | ||||||
| 327 | html => '', | ||||||
| 328 | ltx => "\\textbf{" | ||||||
| 329 | }, | ||||||
| 330 | close => { | ||||||
| 331 | html => '', | ||||||
| 332 | ltx => '}', | ||||||
| 333 | } | ||||||
| 334 | }, | ||||||
| 335 | 'code' => { | ||||||
| 336 | open => { | ||||||
| 337 | html => '', |
||||||
| 338 | ltx => "\\texttt{", | ||||||
| 339 | }, | ||||||
| 340 | close => { | ||||||
| 341 | html => '', | ||||||
| 342 | ltx => '}', | ||||||
| 343 | } | ||||||
| 344 | }, | ||||||
| 345 | 'strike' => { | ||||||
| 346 | open => { | ||||||
| 347 | html => ' |
||||||
| 348 | ltx => "\\sout{" | ||||||
| 349 | }, | ||||||
| 350 | close => { | ||||||
| 351 | html => '', | ||||||
| 352 | ltx => '}', | ||||||
| 353 | } | ||||||
| 354 | }, | ||||||
| 355 | 'del' => { | ||||||
| 356 | open => { | ||||||
| 357 | html => ' |
||||||
| 358 | ltx => "\\sout{" | ||||||
| 359 | }, | ||||||
| 360 | close => { | ||||||
| 361 | html => '', | ||||||
| 362 | ltx => '}', | ||||||
| 363 | } | ||||||
| 364 | }, | ||||||
| 365 | 'sup' => { | ||||||
| 366 | open => { | ||||||
| 367 | html => '', | ||||||
| 368 | ltx => "\\textsuperscript{" | ||||||
| 369 | }, | ||||||
| 370 | close => { | ||||||
| 371 | html => '', | ||||||
| 372 | ltx => '}', | ||||||
| 373 | } | ||||||
| 374 | }, | ||||||
| 375 | 'sub' => { | ||||||
| 376 | open => { | ||||||
| 377 | html => '', | ||||||
| 378 | ltx => "\\textsubscript{" | ||||||
| 379 | }, | ||||||
| 380 | close => { | ||||||
| 381 | html => '', | ||||||
| 382 | ltx => '}', | ||||||
| 383 | } | ||||||
| 384 | }, | ||||||
| 385 | sf => { | ||||||
| 386 | open => { | ||||||
| 387 | html => '', | ||||||
| 388 | ltx => "\\textsf{" | ||||||
| 389 | }, | ||||||
| 390 | close => { | ||||||
| 391 | html => '', | ||||||
| 392 | ltx => '}', | ||||||
| 393 | } | ||||||
| 394 | }, | ||||||
| 395 | sc => { | ||||||
| 396 | open => { | ||||||
| 397 | html => '', | ||||||
| 398 | ltx => "\\textsc{" | ||||||
| 399 | }, | ||||||
| 400 | close => { | ||||||
| 401 | html => '', | ||||||
| 402 | ltx => '}', | ||||||
| 403 | } | ||||||
| 404 | }, | ||||||
| 405 | }; | ||||||
| 406 | } | ||||||
| 407 | |||||||
| 408 | sub _ltx_replace_ldots { | ||||||
| 409 | 10936 | 10936 | 19549 | my ($self, $string) = @_; | |||
| 410 | 10936 | 16215 | my $ldots = "\\dots{}"; | ||||
| 411 | 10936 | 20140 | $string =~ s/\.{3,4}/$ldots/g ; | ||||
| 412 | 10936 | 22770 | $string =~ s/\x{2026}/$ldots/g; | ||||
| 413 | 10936 | 20199 | return $string; | ||||
| 414 | } | ||||||
| 415 | |||||||
| 416 | sub _ltx_replace_slash { | ||||||
| 417 | 10936 | 10936 | 19190 | my ($self, $string) = @_; | |||
| 418 | 10936 | 19241 | $string =~ s!/!\\Slash{}!g; | ||||
| 419 | 10936 | 19486 | return $string; | ||||
| 420 | } | ||||||
| 421 | |||||||
| 422 | # https://unicode.org/udhr/n/notes_fra.html | ||||||
| 423 | # espace fine insécable ; espace justifiante | ||||||
| 424 | # espace fine insécable ! espace justifiante | ||||||
| 425 | # espace fine insécable ? espace justifiante | ||||||
| 426 | |||||||
| 427 | # espace mots insécable : espace justifiante | ||||||
| 428 | # espace mots insécable » espace justifiante | ||||||
| 429 | |||||||
| 430 | # espace justifiante « espace mots insécable | ||||||
| 431 | |||||||
| 432 | # espace justifiante tiret espace justifiante | ||||||
| 433 | # pas de blanc , espace justifiante | ||||||
| 434 | # pas de blanc . espace justifiante | ||||||
| 435 | # espace justifiante ( pas de blanc | ||||||
| 436 | # espace justifiante [ pas de blanc | ||||||
| 437 | # pas de blanc ) espace justifiante | ||||||
| 438 | # pas de blanc ] espace justifiante | ||||||
| 439 | |||||||
| 440 | |||||||
| 441 | sub _html_french_punctuation { | ||||||
| 442 | 41 | 41 | 75 | my ($self, $string) = @_; | |||
| 443 | |||||||
| 444 | # try the # | ||||||
| 445 | |||||||
| 446 | # optional space, punct, and then either space or end of line | ||||||
| 447 | 41 | 120 | my $chars = qr{[\x{20}\x{a0}\x{202f}\(\)\[\]\.\,\:«»\;\!\?]}; | ||||
| 448 | 41 | 92 | my $ws = qr{[\x{20}\x{a0}\x{202f}]}; | ||||
| 449 | 41 | 553 | $string =~ s/$ws*([;!?])(?=$chars)/\x{202f}$1/gs; | ||||
| 450 | 41 | 332 | $string =~ s/$ws*([;!?])$/\x{202f}$1/gms; | ||||
| 451 | |||||||
| 452 | # ditto | ||||||
| 453 | 41 | 343 | $string =~ s/$ws*([:»])(?=$chars)/\x{a0}$1/gs; | ||||
| 454 | 41 | 281 | $string =~ s/$ws*([:»])$/\x{a0}$1/gms; | ||||
| 455 | |||||||
| 456 | 41 | 196 | $string =~ s/^«$ws*/«\x{a0}/gms; | ||||
| 457 | 41 | 255 | $string =~ s/(?<=$chars)«$ws*/«\x{a0}/gs; | ||||
| 458 | 41 | 166 | return $string; | ||||
| 459 | } | ||||||
| 460 | |||||||
| 461 | |||||||
| 462 | =item escape_all_html($string) | ||||||
| 463 | |||||||
| 464 | HTML escape | ||||||
| 465 | |||||||
| 466 | =cut | ||||||
| 467 | |||||||
| 468 | sub escape_all_html { | ||||||
| 469 | 15583 | 15583 | 1 | 26531 | my ($self, $string) = @_; | ||
| 470 | 15583 | 34309 | $string =~ s/&/&/g; | ||||
| 471 | 15583 | 24492 | $string =~ s/</g; | ||||
| 472 | 15583 | 24525 | $string =~ s/>/>/g; | ||||
| 473 | 15583 | 25208 | $string =~ s/"/"/g; | ||||
| 474 | 15583 | 24688 | $string =~ s/'/'/g; | ||||
| 475 | 15583 | 76785 | return $string; | ||||
| 476 | } | ||||||
| 477 | |||||||
| 478 | =item escape_tex | ||||||
| 479 | |||||||
| 480 | Escape the string for LaTeX output | ||||||
| 481 | |||||||
| 482 | =cut | ||||||
| 483 | |||||||
| 484 | sub escape_tex { | ||||||
| 485 | 12185 | 12185 | 1 | 21795 | my ($self, $string) = @_; | ||
| 486 | 12185 | 28869 | $string =~ s/\\/\\textbackslash{}/g; | ||||
| 487 | 12185 | 20717 | $string =~ s/#/\\#/g ; | ||||
| 488 | 12185 | 19685 | $string =~ s/\$/\\\$/g; | ||||
| 489 | 12185 | 19789 | $string =~ s/%/\\%/g; | ||||
| 490 | 12185 | 19397 | $string =~ s/&/\\&/g; | ||||
| 491 | 12185 | 18910 | $string =~ s/_/\\_/g ; | ||||
| 492 | 12185 | 19023 | $string =~ s/\{/\\{/g ; | ||||
| 493 | 12185 | 19844 | $string =~ s/\}/\\}/g ; | ||||
| 494 | 12185 | 19519 | $string =~ s/\\textbackslash\\\{\\\}/\\textbackslash{}/g; | ||||
| 495 | 12185 | 19140 | $string =~ s/~/\\textasciitilde{}/g ; | ||||
| 496 | 12185 | 19253 | $string =~ s/\^/\\^{}/g ; | ||||
| 497 | 12185 | 18158 | $string =~ s/\|/\\textbar{}/g; | ||||
| 498 | 12185 | 25520 | return $string; | ||||
| 499 | } | ||||||
| 500 | |||||||
| 501 | |||||||
| 502 | =item is_latex | ||||||
| 503 | |||||||
| 504 | Shortcut to check if the format is latex | ||||||
| 505 | |||||||
| 506 | =item is_html | ||||||
| 507 | |||||||
| 508 | Shortcut to check if the format is html | ||||||
| 509 | |||||||
| 510 | =cut | ||||||
| 511 | |||||||
| 512 | sub is_latex { | ||||||
| 513 | 29394 | 29394 | 1 | 52969 | shift->fmt eq 'ltx'; | ||
| 514 | } | ||||||
| 515 | |||||||
| 516 | sub is_html { | ||||||
| 517 | 16101 | 16101 | 1 | 27041 | shift->fmt eq 'html'; | ||
| 518 | } | ||||||
| 519 | |||||||
| 520 | =item unroll | ||||||
| 521 | |||||||
| 522 | Convert the close_inline open_inline symbols (= and *) into elements | ||||||
| 523 | an open/close type and the tag properly set. | ||||||
| 524 | |||||||
| 525 | =cut | ||||||
| 526 | |||||||
| 527 | sub unroll { | ||||||
| 528 | 1486 | 1486 | 1 | 2316 | my $self = shift; | ||
| 529 | 1486 | 2125 | my @new; | ||||
| 530 | 1486 | 6048 | my %map = ( | ||||
| 531 | '=' => [qw/code/], | ||||||
| 532 | '*' => [qw/em/], | ||||||
| 533 | '**' => [qw/strong/], | ||||||
| 534 | '***' => [qw/strong em/], | ||||||
| 535 | ); | ||||||
| 536 | 1486 | 100 | 2900 | if ($self->type eq 'open_inline') { | |||
| 50 | |||||||
| 537 | 750 | 1346 | push @new, map { +{ type => 'open', tag => $_ } } @{$map{$self->tag}}; | ||||
| 852 | 2977 | ||||||
| 750 | 1423 | ||||||
| 538 | } | ||||||
| 539 | elsif ($self->type eq 'close_inline') { | ||||||
| 540 | 736 | 1287 | push @new, map { +{ type => 'close', tag => $_ } } reverse @{$map{$self->tag}}; | ||||
| 838 | 2491 | ||||||
| 736 | 1396 | ||||||
| 541 | } | ||||||
| 542 | else { | ||||||
| 543 | 0 | 0 | die "unroll can be called only on close_inline/open_inline, not " . $self->type . " " . $self->string; | ||||
| 544 | } | ||||||
| 545 | 1486 | 2841 | return map { __PACKAGE__->new(%$_, string => '', fmt => $self->fmt) } @new; | ||||
| 1690 | 5233 | ||||||
| 546 | } | ||||||
| 547 | |||||||
| 548 | =item verbatim_string($string) | ||||||
| 549 | |||||||
| 550 | Escape the string according to the element format | ||||||
| 551 | |||||||
| 552 | =cut | ||||||
| 553 | |||||||
| 554 | sub verbatim_string { | ||||||
| 555 | 2972 | 2972 | 1 | 6204 | my ($self, $string) = @_; | ||
| 556 | 2972 | 100 | 6469 | if ($self->is_latex) { | |||
| 50 | |||||||
| 557 | 1249 | 2902 | return $self->escape_tex($string); | ||||
| 558 | } | ||||||
| 559 | elsif ($self->is_html) { | ||||||
| 560 | 1723 | 3747 | return $self->escape_all_html($string); | ||||
| 561 | } | ||||||
| 562 | else { | ||||||
| 563 | 0 | die "Not reached"; | |||||
| 564 | } | ||||||
| 565 | } | ||||||
| 566 | |||||||
| 567 | =back | ||||||
| 568 | |||||||
| 569 | =cut | ||||||
| 570 | |||||||
| 571 | 1; |