Passed
Push — master ( 74de7d...e6942a )
by Guillaume
05:12
created

TailwindCSS::removeUnwantedJavaScript()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
namespace App\Docsets;
4
5
use Godbout\DashDocsetBuilder\Docsets\BaseDocset;
6
use Illuminate\Support\Collection;
7
use Illuminate\Support\Facades\Storage;
8
use Illuminate\Support\Str;
9
use Wa72\HtmlPageDom\HtmlPageCrawler;
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://play.tailwindcss.com/';
18
    public const ICON_16 = 'favicon-16x16.png';
19
    public const ICON_32 = 'favicon-32x32.png';
20
    public const EXTERNAL_DOMAINS = [
21
    ];
22
23
24
    public function grab(): bool
25
    {
26
        $toIgnore = implode('|', [
27
            'blog.tailwindcss.com',
28
        ]);
29
30
        system(
31
            "echo; wget tailwindcss.com/docs \
32
                --mirror \
33
                --trust-server-names \
34
                --reject-regex='{$toIgnore}' \
35
                --page-requisites \
36
                --adjust-extension \
37
                --convert-links \
38
                --span-hosts \
39
                --domains={$this->externalDomains()} \
40
                --directory-prefix=storage/{$this->downloadedDirectory()} \
41
                -e robots=off \
42
                --quiet \
43
                --show-progress",
44
            $result
45
        );
46
47
        return $result === 0;
48
    }
49
50 16
    public function entries(string $file): Collection
51
    {
52 16
        $crawler = HtmlPageCrawler::create(Storage::get($file));
53
54 16
        $entries = collect();
55
56 16
        $entries = $entries->union($this->resourceEntries($crawler, $file));
57 16
        $entries = $entries->union($this->guideEntries($crawler, $file));
58 16
        $entries = $entries->union($this->sectionEntries($crawler, $file));
59
60 16
        return $entries;
61
    }
62
63 16
    protected function resourceEntries(HtmlPageCrawler $crawler, string $file)
64
    {
65 16
        $entries = collect();
66
67 16
        if (Str::contains($file, "{$this->url()}/resources.html")) {
68 16
            $crawler->filter('h2')->each(function (HtmlPageCrawler $node) use ($entries, $file) {
69 16
                $entries->push([
70 16
                    'name' => $this->cleanAnchorText($node->text()),
71 16
                    'type' => 'Resource',
72 16
                    'path' => Str::after($file . '#' . Str::slug($node->text()), $this->innerDirectory()),
73
                ]);
74 16
            });
75
76 16
            $crawler->filter('h3')->each(function (HtmlPageCrawler $node) use ($entries, $file) {
77 16
                $entries->push([
78 16
                    'name' => $this->cleanAnchorText($node->text()),
79 16
                    'type' => 'Section',
80 16
                    'path' => Str::after($file . '#' . Str::slug($node->text()), $this->innerDirectory()),
81
                ]);
82 16
            });
83
84 16
            return $entries;
85
        }
86 16
    }
87
88 16
    protected function guideEntries(HtmlPageCrawler $crawler, string $file)
89
    {
90 16
        $entries = collect();
91
92 16
        if (Str::contains($file, "{$this->url()}/docs.html")) {
93 8
            $itemsToIgnore = collect(['Release Notes', 'Typography', 'Forms', 'Aspect Ratio', 'Line Clamp']);
94
95
            $crawler
96 8
                ->filter('nav#nav li.mt-8 a')
97 8
                ->each(function (HtmlPageCrawler $node) use ($entries, $itemsToIgnore) {
98 8
                    if (! $itemsToIgnore->contains($node->text())) {
99 8
                        $entries->push([
100 8
                            'name' => trim($node->text()),
101 8
                            'type' => 'Guide',
102 8
                            'path' => $this->url() . '/' . $node->attr('href'),
103
                        ]);
104
                    }
105 8
                });
106
        }
107
108 16
        return $entries;
109
    }
110
111 16
    protected function sectionEntries(HtmlPageCrawler $crawler, string $file)
112
    {
113 16
        $entries = collect();
114
115 16
        $crawler->filter('h2')->each(function (HtmlPageCrawler $node) use ($entries, $file) {
116 16
            $entries->push([
117 16
                'name' => $this->cleanAnchorText($node->text()),
118 16
                'type' => 'Section',
119 16
                'path' => Str::after($file . '#' . Str::slug($node->text()), $this->innerDirectory()),
120
            ]);
121 16
        });
122
123 16
        return $entries;
124
    }
125
126 16
    public function format(string $file): string
127
    {
128 16
        $crawler = HtmlPageCrawler::create(Storage::get($file));
129
130 16
        $this->removeAnnouncementBar($crawler);
131 16
        $this->removeTopbar($crawler);
132 16
        $this->removeLeftSidebar($crawler);
133 16
        $this->removeRightSidebar($crawler);
134 16
        $this->removeBottomMenuButton($crawler);
135
136 16
        $this->updateContainerWidth($crawler);
137 16
        $this->updateBottomPadding($crawler);
138
139 16
        $this->ignoreDarkModeForSomeColors($crawler);
140
141 16
        $this->removeUnwantedJavaScript($crawler);
142
143 16
        $this->insertOnlineRedirection($crawler, $file);
144 16
        $this->insertDashTableOfContents($crawler, $file);
145
146 16
        return $crawler->saveHTML();
147
    }
148
149 16
    protected function removeAnnouncementBar(HtmlPageCrawler $crawler)
150
    {
151 16
        $crawler->filter('#__next > div.from-indigo-600.to-light-blue-500')->remove();
152 16
    }
153
154 16
    protected function removeTopbar(HtmlPageCrawler $crawler)
155
    {
156 16
        $crawler->filter('div.sticky.top-0')->remove();
157 16
    }
158
159 16
    protected function removeLeftSidebar(HtmlPageCrawler $crawler)
160
    {
161 16
        $crawler->filter('#sidebar')->remove();
162 16
    }
163
164 16
    protected function removeRightSidebar(HtmlPageCrawler $crawler)
165
    {
166 16
        $crawler->filter('#content-wrapper div.hidden.flex-none.w-64')->remove();
167 16
    }
168
169 16
    protected function removeBottomMenuButton(HtmlPageCrawler $crawler)
170
    {
171 16
        $crawler->filter('#__next > button[type=button]')->remove();
172 16
    }
173
174 16
    protected function updateContainerWidth(HtmlPageCrawler $crawler)
175
    {
176 16
        $crawler->filter('#content-wrapper')->addClass('px-4');
177 16
    }
178
179 16
    protected function updateBottomPadding(HtmlPageCrawler $crawler)
180
    {
181 16
        $crawler->filter('#content-wrapper > div > div')
182 16
            ->removeClass('pb-24')
183 16
            ->addClass('pb-10')
184
        ;
185 16
    }
186
187 16
    protected function ignoreDarkModeForSomeColors(HtmlPageCrawler $crawler)
188
    {
189 16
        $this->ignoreDarkModeForDefaultColorPaletteSection($crawler);
190 16
        $this->ignoreDarkModeForVariousColorTables($crawler);
191 16
    }
192
193 16
    protected function ignoreDarkModeForDefaultColorPaletteSection(HtmlPageCrawler $crawler)
194
    {
195 16
        $crawler->filter('div.h-10.w-full.rounded.ring-1.ring-inset')->addClass('dash-ignore-dark-mode');
196 16
    }
197
198 16
    protected function ignoreDarkModeForVariousColorTables(HtmlPageCrawler $crawler)
199
    {
200 16
        $crawler->filter('h2 + div td:last-child')->addClass('dash-ignore-dark-mode');
201 16
    }
202
203 16
    protected function removeUnwantedJavaScript(HtmlPageCrawler $crawler)
204
    {
205 16
        $crawler->filter('script')->remove();
206 16
    }
207
208 16
    protected function insertOnlineRedirection(HtmlPageCrawler $crawler, string $file)
209
    {
210 16
        $onlineUrl = Str::substr(Str::after($file, $this->innerDirectory()), 1, -5);
211
212 16
        $crawler->filter('html')->prepend("<!-- Online page at https://$onlineUrl -->");
213 16
    }
214
215 16
    protected function insertDashTableOfContents(HtmlPageCrawler $crawler, string $file)
216
    {
217 16
        if (! Str::contains($file, "{$this->url()}/docs.html")) {
218 16
            $crawler->filter('body')
219 16
                ->before('<a name="//apple_ref/cpp/Section/Top" class="dashAnchor"></a>');
220
221 16
            $crawler->filter('h2, h3')->each(function (HtmlPageCrawler $node) {
222 16
                $node->prepend(
223 16
                    '<a id="' . Str::slug($node->text()) . '" name="//apple_ref/cpp/Section/' . rawurlencode($this->cleanAnchorText($node->text())) . '" class="dashAnchor"></a>'
224
                );
225 16
            });
226
        }
227 16
    }
228
229 24
    protected function cleanAnchorText($anchorText)
230
    {
231 24
        return trim(preg_replace('/\s+/', ' ', $anchorText));
232
    }
233
}
234