Passed
Push — master ( 510264...8fb659 )
by Guillaume
05:51
created

TailwindCSS   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 263
Duplicated Lines 0 %

Test Coverage

Coverage 88.68%

Importance

Changes 13
Bugs 0 Features 1
Metric Value
wmc 25
eloc 137
c 13
b 0
f 1
dl 0
loc 263
ccs 141
cts 159
cp 0.8868
rs 10

20 Methods

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