Test Failed
Pull Request — master (#5)
by
unknown
03:17
created

LaTeXFormatter::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 4
rs 10
1
<?php
2
/**
3
 * Highlighter
4
 *
5
 * Copyright (C) 2016, Some right reserved.
6
 *
7
 * @author Kacper "Kadet" Donat <[email protected]>
8
 *
9
 * Contact with author:
10
 * Xmpp:   [email protected]
11
 * E-mail: [email protected]
12
 *
13
 * From Kadet with love.
14
 */
15
16
namespace Kadet\Highlighter\Formatter;
17
18
use Kadet\Highlighter\Parser\Token\Token;
19
use Kadet\Highlighter\Parser\Tokens;
20
use Kadet\Highlighter\Utils\ArrayHelper;
21
22
/**
23
 * Class LateXFormatter
24
 *
25
 * @package Kadet\Highlighter\Formatter
26
 */
27
class LaTeXFormatter implements FormatterInterface
28
{
29
    private $_styles;
30
31
    public function __construct($styles = false)
32
    {
33
        $this->_styles = $styles ?: include __DIR__.'/../Styles/LaTeX/Default.php';
34
    }
35
36
    public function format(Tokens $tokens)
37
    {
38
        $source = $tokens->getSource();
39
40
        $result = '';
41
        $last   = 0;
42
43
        /** @var Token $token */
44
        foreach ($tokens as $token) {
45
            list($openTag, $closeTag) = $this->getOpenCloseTags($token);
46
            $result .= $this->escape(substr($source, $last, $token->pos - $last));
47
            $result .= $token->isStart() ? $openTag : $closeTag;
48
49
            $last = $token->pos;
50
        }
51
        $result .= substr($source, $last);
52
53
        return $result;
54
    }
55
56
    protected function escape($token)
57
    {
58
        $replace = [
59
            '\\' => '\\textbackslash{}',
60
            '{' => '\\{',
61
            '}' => '\\}',
62
            // When there is a \ in the source, it gets translated to
63
            // \textasciibackslash{}, but then the { and } are escaped to \{
64
            // and \}. This substitution reverts this.
65
            '\\textbackslash\\{\\}' => '\\textbackslash{}',
66
            '%' => '\\%',
67
            '_' => '\\_',
68
            '^' => '\\textasciicircum{}',
69
            '~' => '\\textasciitilde{}',
70
            '$' => '\\$',
71
            '&' => '\\&',
72
            '<' => '\\textless{}',
73
            '>' => '\\textgreater{}',
74
            '>' => '\\textgreater{}',
75
        ];
76
77
        // We can do just with a simple str_replace() because PHP promises to
78
        // process them sequentially:
79
        // https://secure.php.net/manual/en/function.str-replace.php#refsect1-function.str-replace-parameters
80
        return str_replace(
81
            array_keys($replace),
82
            array_values($replace),
83
            $token
84
        );
85
    }
86
87
    protected function getOpenCloseTags($token)
88
    {
89
        $openTag = $closeTag = '';
90
        $style = $this->getStyle($token);
91
92
        if (ArrayHelper::get($style, 'bold', false)) {
93
            $openTag .= '\\textbf{';
94
            $closeTag .= '}';
95
        }
96
        if (ArrayHelper::get($style, 'italic', false)) {
97
            $openTag .= '\\textsl{';
98
            $closeTag .= '}';
99
        }
100
        if (ArrayHelper::get($style, 'underline', false)) {
101
            $openTag .= '\\underline{';
102
            $closeTag .= '}';
103
        }
104
        if (($color = ArrayHelper::get($style, 'color', 'default')) !== 'default') {
105
            $openTag .= sprintf('\\textcolor{%s}{', $style['color']);
106
            $closeTag .= '}';
107
        }
108
109
        return [$openTag, $closeTag];
110
    }
111
112
    protected function getStyle($token)
113
    {
114
        return ArrayHelper::resolve($this->_styles, $token->name, []);
115
    }
116
}
117