Passed
Push — master ( 531114...eadbff )
by Caen
03:07 queued 12s
created

HydeSmartDocs::renderHeader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Hyde\Framework\Services;
4
5
use Hyde\Framework\Helpers\Features;
6
use Hyde\Framework\Models\Pages\DocumentationPage;
7
use Illuminate\Support\Str;
8
9
/**
10
 * Class to make Hyde documentation pages smarter,
11
 * by dynamically enriching them with semantic HTML.
12
 *
13
 * @experimental 🧪 Subject to change without notice.
14
 *
15
 * @see \Hyde\Framework\Testing\Feature\Services\HydeSmartDocsTest
16
 */
17
class HydeSmartDocs
18
{
19
    protected DocumentationPage $page;
20
    protected string $html;
21
22
    protected string $header;
23
    protected string $body;
24
    protected string $footer;
25
26
    public function __construct(DocumentationPage $page, string $html)
27
    {
28
        $this->page = $page;
29
        $this->html = $html;
30
    }
31
32
    public function renderHeader(): string
33
    {
34
        return $this->header;
35
    }
36
37
    public function renderBody(): string
38
    {
39
        return $this->body;
40
    }
41
42
    public function renderFooter(): string
43
    {
44
        return $this->footer;
45
    }
46
47
    /** @internal */
48
    public function process(): self
49
    {
50
        $this->tokenize();
51
52
        $this->addDynamicHeaderContent();
53
        $this->addDynamicFooterContent();
54
55
        return $this;
56
    }
57
58
    protected function tokenize(): static
59
    {
60
        // The HTML content is expected to be two parts. To create semantic HTML,
61
        // we need to split the content into header and body. We do this by
62
        // extracting the first <h1> tag and everything before it.
63
64
        // Split the HTML content by the first newline
65
        $parts = explode("\n", $this->html, 2);
66
67
        $this->header = $parts[0];
68
        $this->body = $parts[1] ?? '';
69
        $this->footer = '';
70
71
        return $this;
72
    }
73
74
    protected function addDynamicHeaderContent(): static
75
    {
76
        // Hook to add dynamic content to the header.
77
        // This is where we can add TOC, breadcrumbs, etc.
78
79
        if ($this->canRenderSourceLink('header')) {
80
            $this->header .= $this->renderSourceLink();
81
        }
82
83
        return $this;
84
    }
85
86
    protected function addDynamicFooterContent(): static
87
    {
88
        // Hook to add dynamic content to the footer.
89
        // This is where we can add copyright, attributions, info, etc.
90
91
        if (config('torchlight.attribution.enabled', true) && $this->hasTorchlight()) {
92
            $this->footer .= Str::markdown(config(
93
                'torchlight.attribution.markdown',
94
                'Syntax highlighted by torchlight.dev'
95
            ));
96
        }
97
98
        if ($this->canRenderSourceLink('footer')) {
99
            $this->footer .= $this->renderSourceLink();
100
        }
101
102
        return $this;
103
    }
104
105
    protected function renderSourceLink(): string
106
    {
107
        return sprintf(
108
            '<p class="edit-page-link"><a href="%s">%s</a></p>',
109
            $this->page->getOnlineSourcePath(),
0 ignored issues
show
Bug introduced by
It seems like $this->page->getOnlineSourcePath() can also be of type false; however, parameter $values of sprintf() does only seem to accept double|integer|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

109
            /** @scrutinizer ignore-type */ $this->page->getOnlineSourcePath(),
Loading history...
110
            config('docs.edit_source_link_text', 'Edit page')
111
        );
112
    }
113
114
    /**
115
     * Create a new HydeSmartDocs instance, process, and return it.
116
     *
117
     * @param  \Hyde\Framework\Models\Pages\DocumentationPage  $page  The source page object
118
     * @param  string  $html  compiled HTML content
119
     * @return static new processed instance
120
     */
121
    public static function create(DocumentationPage $page, string $html): static
122
    {
123
        return (new self($page, $html))->process();
124
    }
125
126
    /**
127
     * Does the current document use Torchlight?
128
     *
129
     * @return bool
130
     */
131
    public function hasTorchlight(): bool
132
    {
133
        return Features::hasTorchlight() && str_contains($this->html, 'Syntax highlighted by torchlight.dev');
134
    }
135
136
    /**
137
     * Do we satisfy the requirements to render an edit source button in the supplied position?
138
     *
139
     * @param  string  $inPosition
140
     * @return bool
141
     */
142
    protected function canRenderSourceLink(string $inPosition): bool
143
    {
144
        $config = config('docs.edit_source_link_position', 'both');
145
        $positions = $config === 'both' ? ['header', 'footer'] : [$config];
146
147
        return ($this->page->getOnlineSourcePath() !== false) && in_array($inPosition, $positions);
148
    }
149
}
150