This repository was archived by the owner on Dec 9, 2017. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathDeferrer.php
More file actions
126 lines (111 loc) · 2.85 KB
/
Deferrer.php
File metadata and controls
126 lines (111 loc) · 2.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
<?php
/*
* This file is part of a XenForo add-on.
*
* (c) Jeremy P <https://xenforo.com/community/members/jeremy-p.450/>
* Parts derived from XFOptimise by Luke Foreman
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/
namespace Jrahmy\DeferJs;
/**
* Provides a means to move all javascript to the end of the page.
*
* @author Jeremy P <https://xenforo.com/community/members/jeremy-p.450/>
*/
class Deferrer
{
/**
* The output we're filtering.
*
* @var string
*/
protected $output;
/**
* The blacklisted search terms.
*
* @var array
*/
protected $blacklist;
/**
* Concatenated deferred matches.
*
* @var string
*/
protected $deferred;
/**
* Constructor.
*
* @param string $output The output to filter
* @param array $blacklist An array of blacklisted snippets
*/
public function __construct($output, array $blacklist)
{
$this->output = $output;
$this->blacklist = $blacklist;
}
/**
* Defer all (un)matching javascripts.
*
* @return string The filtered output
*/
public function defer()
{
// scoop up unblacklisted javascripts
$this->output = preg_replace_callback(
'/\s*?<script.*?>.*?<\/script>\s*?/is',
[$this, 'collect'],
$this->output
);
// place them before the body tag
$this->output = preg_replace(
'/(<\/body>)/i',
$this->deferred.'$1',
$this->output,
1
);
return $this->output;
}
/**
* Collect unblacklisted scripts into the deferred property. To be used
* with preg_replace_callback().
*
* @param array $matches An array of matches
*
* @return string The matched JS if blacklisted, or nothing otherwise
*/
protected function collect($matches)
{
// swap comments for CDATA
$matches[0] = str_replace(
['<!--', '-->'],
[' /* <![CDATA[ */ ', ' /* ]]> */ '],
$matches[0]
);
if ($this->blacklisted($matches[0])) {
// leave match in place
return $matches[0];
}
$this->deferred .= trim($matches[0]);
// remove match from output
return '';
}
/**
* Check if the given match contains any blacklisted code.
*
* @param string $match The match to search
*
* @return bool True if blacklisted, false if not
*/
protected function blacklisted($match)
{
// cycle through for matches
foreach ($this->blacklist as $snippet) {
if (stripos($match, $snippet) !== false) {
return true;
}
}
return false;
}
}