Passed
Push — master ( ff576e...774618 )
by Guillaume
05:39
created

TailwindCSS::entries()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 1

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 9
c 4
b 0
f 0
dl 0
loc 14
ccs 10
cts 10
cp 1
rs 9.9666
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace App\Docsets;
4
5
use Illuminate\Support\Str;
6
use Wa72\HtmlPageDom\HtmlPage;
7
use Illuminate\Support\Collection;
8
use Wa72\HtmlPageDom\HtmlPageCrawler;
9
use Illuminate\Support\Facades\Storage;
10
11
class TailwindCSS extends BaseDocset
12
{
13
    public const CODE = 'tailwindcss';
14
    public const NAME = 'Tailwind CSS';
15
    public const URL = 'tailwindcss.com';
16
    public const INDEX = 'docs/installation.html';
17
    public const PLAYGROUND = 'https://codesandbox.io/s/github/lbogdan/tailwindcss-playground';
18
    public const ICON_16 = 'favicon-16x16.png';
19
    public const ICON_32 = 'favicon-32x32.png';
20
    public const EXTERNAL_DOMAINS = [
21
        'refactoring-ui.nyc3.cdn.digitaloceanspaces.com',
22
        'jsdelivr.net',
23
        'code.jquery.com',
24
        'rsms.me',
25
        'googleapis.com',
26
        // 'images.unsplash.com'
27
    ];
28
29 1
    public function entries(string $file): Collection
30
    {
31 1
        $crawler = HtmlPageCrawler::create(Storage::get($file));
32
33 1
        $entries = collect();
34
35 1
        $entries = $entries->merge($this->environmentEntries($crawler, $file));
36 1
        $entries = $entries->merge($this->instructionEntries($crawler, $file));
37 1
        $entries = $entries->merge($this->sampleEntries($crawler, $file));
38 1
        $entries = $entries->merge($this->resourceEntries($crawler, $file));
39 1
        $entries = $entries->merge($this->guideEntries($crawler, $file));
40 1
        $entries = $entries->merge($this->sectionEntries($crawler, $file));
41
42 1
        return $entries;
43
    }
44
45 1
    protected function environmentEntries(HtmlPageCrawler $crawler, string $file)
46
    {
47 1
        $entries = collect();
48
49 1
        if (basename($file) === 'community.html') {
50
            $crawler->filter('h2')->each(function (HtmlPageCrawler $node) use ($entries, $file) {
51
                $entries->push([
52
                    'name' => $this->cleanAnchorText($node->text()),
53
                    'type' => 'Environment',
54
                    'path' => Str::after($file . '#' . Str::slug($node->text()), $this->innerDirectory()),
55
                ]);
56
            });
57
58
            return $entries;
59
        }
60 1
    }
61
62 1
    protected function instructionEntries(HtmlPageCrawler $crawler, string $file)
63
    {
64 1
        $entries = collect();
65
66 1
        if (basename($file) === 'screencasts.html') {
67
            $crawler->filter('span.relative')->each(function (HtmlPageCrawler $node) use ($entries) {
68
                $entries->push([
69
                    'name' => $this->cleanAnchorText($node->text()),
70
                    'type' => 'Instruction',
71
                    'path' => $this->url() . '/' . $node->parents()->first()->attr('href'),
72
                ]);
73
            });
74
75
            return $entries;
76
        }
77 1
    }
78
79 1
    protected function sampleEntries(HtmlPageCrawler $crawler, string $file)
80
    {
81 1
        $entries = collect();
82
83 1
        if (basename($file) === 'components.html') {
84
            $crawler->filter('span.relative')->each(function (HtmlPageCrawler $node) use ($entries) {
85
                $entries->push([
86
                    'name' => $this->cleanAnchorText($node->text()),
87
                    'type' => 'Sample',
88
                    'path' => $this->url() . '/' . $node->parents()->first()->attr('href'),
89
                ]);
90
            });
91
92
            return $entries;
93
        }
94 1
    }
95
96 1
    protected function resourceEntries(HtmlPageCrawler $crawler, string $file)
97
    {
98 1
        $entries = collect();
99
100 1
        if (basename($file) === 'resources.html') {
101
            $crawler->filter('h2')->each(function (HtmlPageCrawler $node) use ($entries, $file) {
102 1
                $entries->push([
103 1
                    'name' => $this->cleanAnchorText($node->text()),
104 1
                    'type' => 'Resource',
105 1
                    'path' => Str::after($file . '#' . Str::slug($node->text()), $this->innerDirectory()),
106
                ]);
107 1
            });
108
109
            $crawler->filter('h3')->each(function (HtmlPageCrawler $node) use ($entries, $file) {
110 1
                $entries->push([
111 1
                    'name' => $this->cleanAnchorText($node->text()),
112 1
                    'type' => 'Section',
113 1
                    'path' => Str::after($file . '#' . Str::slug($node->text()), $this->innerDirectory()),
114
                ]);
115 1
            });
116
117 1
            return $entries;
118
        }
119 1
    }
120
121 1
    protected function guideEntries(HtmlPageCrawler $crawler, string $file)
122
    {
123 1
        $pageTitle = (new HtmlPage(Storage::get($file)))->getTitle();
124
125 1
        $entries = collect();
126
127 1
        if ($pageTitle === 'Installation - Tailwind CSS') {
128
            $crawler->filter('#navWrapper li a')->each(function (HtmlPageCrawler $node) use ($entries) {
129 1
                $entries->push([
130 1
                    'name' => trim($node->text()),
131 1
                    'type' => 'Guide',
132 1
                    'path' => $this->url() . '/docs/' . $node->attr('href'),
133
                ]);
134 1
            });
135
        }
136
137 1
        return $entries;
138
    }
139
140 1
    protected function sectionEntries(HtmlPageCrawler $crawler, string $file)
141
    {
142 1
        $entries = collect();
143
144
        $crawler->filter('h2')->each(function (HtmlPageCrawler $node) use ($entries, $file) {
145 1
            $entries->push([
146 1
                'name' => $this->cleanAnchorText($node->text()),
147 1
                'type' => 'Section',
148 1
                'path' => Str::after($file . '#' . Str::slug($node->text()), $this->innerDirectory()),
149
            ]);
150 1
        });
151
152 1
        return $entries;
153
    }
154
155 1
    public function format(string $html): string
156
    {
157 1
        $crawler = HtmlPageCrawler::create($html);
158
159 1
        $this->removeNavbarAndHeader($crawler);
160 1
        $this->removeLeftSidebar($crawler);
161 1
        $this->removeRightSidebar($crawler);
162 1
        $this->removeTailwindUIAlert($crawler);
163 1
        $this->removeUnwantedCSS($crawler);
164 1
        $this->removeUnwantedJavaScript($crawler);
165 1
        $this->updateCSS($crawler);
166 1
        $this->insertDashTableOfContents($crawler);
167
168 1
        return $crawler->saveHTML();
169
    }
170
171 1
    protected function removeNavbarAndHeader(HtmlPageCrawler $crawler)
172
    {
173 1
        $crawler->filter('body > div:first-child')->remove();
174 1
    }
175
176 1
    protected function removeLeftSidebar(HtmlPageCrawler $crawler)
177
    {
178 1
        $crawler->filter('#sidebar')->remove();
179 1
    }
180
181 1
    protected function removeRightSidebar(HtmlPageCrawler $crawler)
182
    {
183 1
        $crawler->filter('#app div.flex > div.hidden')->remove();
184 1
    }
185
186 1
    protected function removeTailwindUIAlert(HtmlPageCrawler $crawler)
187
    {
188 1
        $crawler->filter('body > div.transition.transform.fixed.z-100')->remove();
189 1
    }
190
191 1
    protected function removeUnwantedCSS(HtmlPageCrawler $crawler)
192
    {
193 1
        $crawler->filter('link[href*="docsearch.min.css"]')->remove();
194 1
    }
195
196 1
    protected function removeUnwantedJavaScript(HtmlPageCrawler $crawler)
197
    {
198 1
        $crawler->filter('script[src*=analytics]')->remove();
199 1
        $crawler->filter('script[src*=docsearch]')->remove();
200 1
        $crawler->filter('script[src*=gtag]')->remove();
201 1
        $crawler->filterXPath("//script[text()[contains(.,'docsearch')]]")->remove();
202 1
        $crawler->filterXPath("//script[text()[contains(.,'gtag')]]")->remove();
203 1
        $crawler->filter('script[src*=jquery]')
204 1
            ->removeAttribute('integrity')
205 1
            ->removeAttribute('crossorigin');
206 1
    }
207
208 1
    protected function updateCSS(HtmlPageCrawler $crawler)
209
    {
210 1
        $this->updateTopPadding($crawler);
211 1
        $this->updateHeader($crawler);
212 1
        $this->updateContainerWidth($crawler);
213 1
        $this->updateBottomPadding($crawler);
214 1
    }
215
216 1
    protected function updateTopPadding(HtmlPageCrawler $crawler)
217
    {
218 1
        $crawler->filter('#app > div')
219 1
            ->removeClass('pt-12')
220 1
            ->removeClass('pt-24')
221 1
            ->removeClass('pb-16')
222 1
            ->removeClass('lg:pt-28')
223 1
            ->removeClass('lg:pt-12')
224
        ;
225 1
    }
226
227 1
    protected function updateHeader(HtmlPageCrawler $crawler)
228
    {
229 1
        $crawler->filter('#app > div > div.markdown')
230 1
            ->removeClass('lg:ml-0')
231 1
            ->removeClass('lg:mr-auto')
232 1
            ->removeClass('xl:mx-0')
233 1
            ->removeClass('xl:w-3/4')
234 1
            ->removeClass('max-w-3xl')
235 1
            ->removeClass('xl:px-12')
236
        ;
237 1
    }
238
239 1
    protected function updateContainerWidth(HtmlPageCrawler $crawler)
240
    {
241 1
        $crawler->filter('body > div:first-child')
242 1
            ->removeClass('max-w-screen-xl');
243
244 1
        $crawler->filter('#content-wrapper')
245 1
            ->removeClass('lg:static')
246 1
            ->removeClass('lg:max-h-full')
247 1
            ->removeClass('lg:overflow-visible')
248 1
            ->removeClass('lg:w-3/4')
249 1
            ->removeClass('xl:w-4/5');
250
251 1
        $crawler->filter('#app > div > div.flex > div.markdown')
252 1
            ->removeClass('xl:p-12')
253 1
            ->removeClass('max-w-3xl')
254 1
            ->removeClass('lg:ml-0')
255 1
            ->removeClass('lg:mr-auto')
256 1
            ->removeClass('xl:w-3/4')
257 1
            ->removeClass('xl:px-12')
258 1
            ->removeClass('xl:mx-0');
259 1
    }
260
261 1
    protected function updateBottomPadding(HtmlPageCrawler $crawler)
262
    {
263 1
        $crawler->filter('body')
264 1
            ->addClass('pb-8');
265 1
    }
266
267 1
    protected function insertDashTableOfContents(HtmlPageCrawler $crawler)
268
    {
269 1
        $crawler->filter('h1')
270 1
            ->before('<a name="//apple_ref/cpp/Section/Top" class="dashAnchor"></a>');
271
272
        $crawler->filter('h2, h3')->each(function (HtmlPageCrawler $node) {
273 1
            $node->prepend(
274 1
                '<a id="' . Str::slug($node->text()) . '" name="//apple_ref/cpp/Section/' . rawurlencode($this->cleanAnchorText($node->text())) . '" class="dashAnchor"></a>'
275
            );
276 1
        });
277 1
    }
278
279 2
    protected function cleanAnchorText($anchorText)
280
    {
281 2
        return trim(preg_replace('/\s+/', ' ', $anchorText));
282
    }
283
}
284