PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.1-beta.2
Jetpack – WP Security, Backup, Speed, & Growth v16.1-beta.2
16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / vendor / wp-php-toolkit / data-liberation / BlockMarkup / class-blockmarkupurlprocessor.php
jetpack / vendor / wp-php-toolkit / data-liberation / BlockMarkup Last commit date
class-blockmarkupprocessor.php 1 week ago class-blockmarkupurlprocessor.php 1 week ago class-blockobject.php 1 week ago
class-blockmarkupurlprocessor.php
543 lines
1 <?php
2
3 namespace WordPress\DataLiberation\BlockMarkup;
4
5 use Rowbot\URL\URL;
6 use WordPress\DataLiberation\URL\URLInTextProcessor;
7 use WordPress\DataLiberation\URL\CSSURLProcessor;
8 use WordPress\DataLiberation\URL\WPURL;
9
10 /**
11 * Reports all the URLs in the imported post and enables rewriting them.
12 */
13 class BlockMarkupUrlProcessor extends BlockMarkupProcessor {
14
15 private $raw_url;
16 /**
17 * @var URL
18 */
19 private $parsed_url;
20 private $base_url_string;
21 private $base_url_object;
22 private $url_in_text_processor;
23 private $url_in_text_node_updated;
24 private $css_url_processor;
25 private $css_url_processor_updated;
26
27 /**
28 * The list of names of URL-related HTML attributes that may be available on
29 * the current token. They will be inspected by next_url_attribute().
30 *
31 * Possible values:
32 *
33 * - null: We haven't inspected any attribute yet.
34 * - array: The first element is the currently inspected attribute
35 * and the rest of the list are elements yet to be inspected on
36 * the upcoming next_url_attribute() call.
37 * - empty array: We've already inspected all the URL-related attributes.
38 *
39 * @var array<string>|null
40 */
41 private $inspecting_html_attributes;
42
43 public function __construct( $html, ?string $base_url_string = null ) {
44 parent::__construct( $html );
45 $this->base_url_string = $base_url_string;
46 $this->base_url_object = $base_url_string ? WPURL::parse( $base_url_string ) : null;
47 }
48
49 public function get_updated_html(): string {
50 if ( $this->url_in_text_node_updated ) {
51 $this->set_modifiable_text( $this->url_in_text_processor->get_updated_text() );
52 $this->url_in_text_node_updated = false;
53 }
54
55 if ( $this->css_url_processor_updated ) {
56 if ( null !== $this->css_url_processor ) {
57 $updated_css = $this->css_url_processor->get_updated_css();
58 $this->set_attribute( 'style', $updated_css );
59 }
60 $this->css_url_processor_updated = false;
61 }
62
63 return parent::get_updated_html();
64 }
65
66 public function get_raw_url() {
67 return $this->raw_url;
68 }
69
70 public function get_parsed_url() {
71 return $this->parsed_url;
72 }
73
74 public function next_token(): bool {
75 $this->get_updated_html();
76
77 $this->raw_url = null;
78 $this->parsed_url = null;
79 $this->inspecting_html_attributes = null;
80 $this->url_in_text_processor = null;
81 $this->css_url_processor = null;
82 /*
83 * Do not reset url_in_text_node_updated or css_url_processor_updated – they're reset
84 * in get_updated_html() which is called in parent::next_token().
85 */
86
87 return parent::next_token();
88 }
89
90 public function next_url() {
91 do {
92 if ( $this->next_url_in_current_token() ) {
93 return true;
94 }
95 } while ( false !== $this->next_token() );
96
97 return false;
98 }
99
100 public function next_url_in_current_token() {
101 $this->raw_url = null;
102 switch ( parent::get_token_type() ) {
103 case '#tag':
104 return $this->next_url_attribute();
105 case '#block-comment':
106 return $this->next_url_block_attribute();
107 case '#text':
108 return $this->next_url_in_text_node();
109 default:
110 return false;
111 }
112 }
113
114 private function next_url_in_text_node() {
115 if ( '#text' !== $this->get_token_type() ) {
116 return false;
117 }
118
119 if ( null === $this->url_in_text_processor ) {
120 /*
121 * Use the base URL for URLs matched in text nodes. This is the only
122 * way to recognize a substring "WordPress.org" as a URL. We might
123 * get some false positives this way, e.g. in this string:
124 *
125 * > And that's how you build a theme. Now let's take a look at..."
126 *
127 * `theme.Now` would be recognized as a URL. It's up to the API consumer
128 * to filter out such false positives e.g. by checking the domain against
129 * a list of accepted domains, or the TLD against a list of public suffixes.
130 */
131 $this->url_in_text_processor = new URLInTextProcessor( $this->get_modifiable_text(), $this->base_url_string );
132 }
133
134 while ( $this->url_in_text_processor->next_url() ) {
135 $this->raw_url = $this->url_in_text_processor->get_raw_url();
136 $this->parsed_url = $this->url_in_text_processor->get_parsed_url();
137
138 return true;
139 }
140
141 return false;
142 }
143
144 /**
145 * Advances to the next CSS URL in the `style` attribute of the current tag token.
146 *
147 * @return bool Whether a CSS URL was found.
148 */
149 private function next_url_in_css() {
150 if ( '#tag' !== $this->get_token_type() ) {
151 return false;
152 }
153
154 if ( null === $this->css_url_processor ) {
155 $css_value = $this->get_attribute( 'style' );
156 if ( ! is_string( $css_value ) ) {
157 return false;
158 }
159
160 $this->css_url_processor = new CSSURLProcessor( $css_value );
161 }
162
163 while ( $this->css_url_processor->next_url() ) {
164 /**
165 * Skip data URIs. They may be really large and they don't
166 * have a hostname to migrate.
167 */
168 if ( $this->css_url_processor->is_data_uri() ) {
169 continue;
170 }
171 $this->raw_url = $this->css_url_processor->get_raw_url();
172 $this->parsed_url = WPURL::parse( $this->raw_url, $this->base_url_string );
173 if ( false === $this->parsed_url ) {
174 continue;
175 }
176
177 return true;
178 }
179
180 return false;
181 }
182
183 private function next_url_attribute() {
184 $tag = $this->get_tag();
185
186 // Check if we have a style attribute with CSS URLs to process.
187 if ( null !== $this->css_url_processor ) {
188 if ( $this->next_url_in_css() ) {
189 return true;
190 }
191 // Done with CSS URLs in this attribute, apply any pending updates and move on.
192 $this->get_updated_html();
193 $this->css_url_processor = null;
194 }
195
196 if ( null === $this->inspecting_html_attributes ) {
197 if ( array_key_exists( $tag, self::HTML_ATTRIBUTES_TO_ACCEPT_RELATIVE_URLS_FROM ) ) {
198 /**
199 * Initialize the list on the first call to next_url_attribute()
200 * for the current token. The last element is the attribute we'll
201 * inspect in the while() loop below.
202 */
203 $this->inspecting_html_attributes = self::HTML_ATTRIBUTES_TO_ACCEPT_RELATIVE_URLS_FROM[ $tag ];
204 // Add style attribute to the list if it exists.
205 if ( null !== $this->get_attribute( 'style' ) ) {
206 $this->inspecting_html_attributes[] = 'style';
207 }
208 } elseif ( null !== $this->get_attribute( 'style' ) ) {
209 $this->inspecting_html_attributes = array( 'style' );
210 } else {
211 return false;
212 }
213 } else {
214 /**
215 * Forget the attribute we've inspected on the previous call to
216 * next_url_attribute().
217 */
218 array_pop( $this->inspecting_html_attributes );
219 }
220
221 while ( count( $this->inspecting_html_attributes ) > 0 ) {
222 $attr = $this->inspecting_html_attributes[ count( $this->inspecting_html_attributes ) - 1 ];
223 $url_maybe = $this->get_attribute( $attr );
224 if ( ! is_string( $url_maybe ) ) {
225 array_pop( $this->inspecting_html_attributes );
226 continue;
227 }
228
229 // Rewrite any CSS `url()` declarations in the `style` attribute.
230 if ( 'style' === $attr ) {
231 $this->css_url_processor = new CSSURLProcessor( $url_maybe );
232 if ( $this->next_url_in_css() ) {
233 return true;
234 }
235 // No CSS URLs found, move to next attribute.
236 $this->css_url_processor = null;
237 array_pop( $this->inspecting_html_attributes );
238 continue;
239 }
240
241 /*
242 * Use base URL to resolve known URI attributes as we are certain we're
243 * dealing with URI values.
244 * With a base URL, the string "plugins.php" in <a href="plugins.php"> will
245 * be correctly recognized as a URL.
246 * Without a base URL, this Processor would incorrectly skip it.
247 */
248 $parsed_url = WPURL::parse( $url_maybe, $this->base_url_string );
249
250 if ( false === $parsed_url ) {
251 array_pop( $this->inspecting_html_attributes );
252 continue;
253 }
254 $this->raw_url = $url_maybe;
255 $this->parsed_url = $parsed_url;
256
257 return true;
258 }
259
260 return false;
261 }
262
263 private function next_url_block_attribute() {
264 while ( $this->next_block_attribute() ) {
265 $url_maybe = $this->get_block_attribute_value();
266 if ( ! is_string( $url_maybe ) ||
267 count( $this->get_block_attribute_path() ) > 1
268 ) {
269 // @TODO: support arrays, objects, and other non-string data structures.
270 continue;
271 }
272
273 /**
274 * Decide whether the current block attribute holds a URL.
275 *
276 * Known URL attributes can be assumed to hold a URL and be
277 * parsed with the base URL. For example, a "/about-us" value
278 * in a wp:navigation-link block's `url` attribute is a
279 * relative URL to the `/about-us` page.
280 *
281 * Other attributes may or may not contain URLs, but we cannot assume
282 * they do. A value `/about-us` could be a relative URL or a class name.
283 * In those cases, we'll let go of relative URLs and only detect
284 * absolute URLs to avoid treating every string as a URL. This requires
285 * parsing without a base URL.
286 */
287 $is_relative_url_block_attribute = (
288 isset( self::BLOCK_ATTRIBUTES_TO_ACCEPT_RELATIVE_URLS_FROM[ $this->get_block_name() ] ) &&
289 in_array( $this->get_block_attribute_key(), self::BLOCK_ATTRIBUTES_TO_ACCEPT_RELATIVE_URLS_FROM[ $this->get_block_name() ], true )
290 );
291
292 /**
293 * Filters whether a block attribute is known to contain a relative URL.
294 *
295 * This filter allows extending the list of block attributes that are
296 * recognized as containing URLs. When a block attribute is marked as
297 * a known URL attribute, it will be parsed with the base URL, allowing
298 * relative URLs to be properly resolved.
299 *
300 * @since 6.8.0
301 *
302 * @param bool $is_relative_url_block_attribute Whether the block attribute is known to contain a relative URL.
303 * @param array $context {
304 * Context information about the block attribute.
305 *
306 * @type string $block_name The name of the block (e.g., 'wp:image', 'wp:button').
307 * @type string $attribute_name The name of the attribute (e.g., 'url', 'href').
308 * }
309 */
310 $is_relative_url_block_attribute = apply_filters(
311 'url_processor_is_relative_url_block_attribute',
312 $is_relative_url_block_attribute,
313 array(
314 'block_name' => $this->get_block_name(),
315 'attribute_name' => $this->get_block_attribute_key(),
316 )
317 );
318
319 $parsed_url = false;
320 if ( $is_relative_url_block_attribute ) {
321 // Known relative URL attribute – let's parse with the base URL.
322 $parsed_url = WPURL::parse( $url_maybe, $this->base_url_string );
323 } else {
324 // Other attributes – let's parse without a base URL (and only detect absolute URLs).
325 $parsed_url = WPURL::parse( $url_maybe );
326 }
327
328 if ( false === $parsed_url ) {
329 continue;
330 }
331
332 $this->raw_url = $url_maybe;
333 $this->parsed_url = $parsed_url;
334 return true;
335 }
336
337 return false;
338 }
339
340 /**
341 * Replaces the currently matched URL with a new one.
342 *
343 * @param string $raw_url The raw URL.
344 * @param URL $parsed_url The parsed version of the raw URL. It is required
345 * as $raw_url might be a relative URL pointing to a different
346 * host than this processor's base URL.
347 *
348 * @return bool True if the URL was set, false otherwise.
349 */
350 public function set_url( $raw_url, $parsed_url ) {
351 if ( null === $this->raw_url ) {
352 return false;
353 }
354 $this->raw_url = $raw_url;
355 $this->parsed_url = $parsed_url;
356 switch ( parent::get_token_type() ) {
357 case '#tag':
358 // Check if we're processing a CSS URL.
359 if ( null !== $this->css_url_processor ) {
360 $this->css_url_processor_updated = true;
361 return $this->css_url_processor->set_raw_url( $raw_url );
362 }
363
364 $attr = $this->get_inspected_attribute_name();
365 if ( false === $attr ) {
366 return false;
367 }
368 $this->set_attribute( $attr, $raw_url );
369
370 return true;
371
372 case '#block-comment':
373 return $this->set_block_attribute_value( $raw_url );
374
375 case '#text':
376 if ( null === $this->url_in_text_processor ) {
377 return false;
378 }
379 $this->url_in_text_node_updated = true;
380
381 return $this->url_in_text_processor->set_raw_url( $raw_url );
382 }
383 }
384
385 /**
386 * Rewrites the components of the currently matched URL from ones
387 * provided in $from_url to ones specified in $to_url.
388 *
389 * It preserves the relative nature of the matched URL.
390 *
391 * @TODO: Should this method live in this class? It's specific to the import process
392 * and the URL rewriting logic and has knowledge about the quirks of detecting
393 * relative URLs in text nodes. On the other hand, the detection is performed
394 * by this WPURL_In_Text_Processor class so maybe the two do go hand in hand?
395 */
396 public function replace_base_url( $to_url, $base_url = null ) {
397 $base_url = $base_url ?? $this->base_url_object;
398 if ( ! $base_url ) {
399 return false;
400 }
401
402 $result = WPURL::replace_base_url(
403 $this->get_parsed_url(),
404 array(
405 'old_base_url' => $base_url,
406 'new_base_url' => $to_url,
407 'raw_url' => $this->get_raw_url(),
408 'is_relative' => (
409 /**
410 * In text nodes, the only detected URLs are absolute. The tricky part
411 * is they may start without a protocol, e.g. `wordpress.org`. Therefore,
412 * we need to tell WPURL::replace_base_url what's our intention regarding
413 * the URL's relativity. It cannot just infer it from the URL itself.
414 */
415 '#text' !== $this->get_token_type() &&
416 ! WPURL::can_parse( $this->get_raw_url() )
417 ),
418 )
419 );
420
421 if ( false === $result ) {
422 return false;
423 }
424
425 $this->set_url( $result . '', $result->new_url );
426
427 return true;
428 }
429
430 /**
431 * Returns true if the currently matched URL is absolute.
432 *
433 * @return bool Whether the currently matched URL is absolute.
434 */
435 public function is_url_absolute() {
436 return WPURL::can_parse( $this->get_raw_url() );
437 }
438
439 public function get_inspected_attribute_name() {
440 if ( '#tag' !== $this->get_token_type() ) {
441 return false;
442 }
443
444 if ( null === $this->inspecting_html_attributes ) {
445 return false;
446 }
447
448 if ( empty( $this->inspecting_html_attributes ) ) {
449 return false;
450 }
451
452 return $this->inspecting_html_attributes[ count( $this->inspecting_html_attributes ) - 1 ];
453 }
454
455 /**
456 * A list of block attributes that are known to contain URLs.
457 *
458 * It covers WordPress core blocks as of WordPress version 6.9. It can be
459 * extended by plugins and themes via the "url_processor_is_relative_url_block_attribute"
460 * filter.
461 *
462 * @var array
463 */
464 public const BLOCK_ATTRIBUTES_TO_ACCEPT_RELATIVE_URLS_FROM = array(
465 'wp:button' => array( 'url', 'linkTarget' ),
466 'wp:cover' => array( 'url' ),
467 'wp:embed' => array( 'url' ),
468 'wp:gallery' => array( 'url', 'fullUrl' ),
469 'wp:image' => array( 'url', 'src', 'href' ),
470 'wp:media-text' => array( 'mediaUrl', 'href' ),
471 'wp:navigation-link' => array( 'url' ),
472 'wp:navigation-submenu' => array( 'url' ),
473 'wp:rss' => array( 'feedURL' ),
474 );
475
476 /**
477 * A list of HTML attributes meant to contain URLs, as defined in the HTML specification.
478 * It includes some deprecated attributes like `lowsrc` and `highsrc` for the `IMG` element.
479 *
480 * See https://html.spec.whatwg.org/multipage/indices.html#attributes-1.
481 * See https://stackoverflow.com/questions/2725156/complete-list-of-html-tag-attributes-which-have-a-url-value.
482 */
483 public const HTML_ATTRIBUTES_TO_ACCEPT_RELATIVE_URLS_FROM = array(
484 'A' => array( 'href' ),
485 'APPLET' => array( 'codebase', 'archive' ),
486 'AREA' => array( 'href' ),
487 'AUDIO' => array( 'src' ),
488 'BASE' => array( 'href' ),
489 'BLOCKQUOTE' => array( 'cite' ),
490 'BODY' => array( 'background' ),
491 'BUTTON' => array( 'formaction' ),
492 'COMMAND' => array( 'icon' ),
493 'DEL' => array( 'cite' ),
494 'EMBED' => array( 'src' ),
495 'FORM' => array( 'action' ),
496 'FRAME' => array( 'longdesc', 'src' ),
497 'HEAD' => array( 'profile' ),
498 'HTML' => array( 'manifest' ),
499 'IFRAME' => array( 'longdesc', 'src' ),
500 // SVG <image> element.
501 'IMAGE' => array( 'href' ),
502 'IMG' => array( 'longdesc', 'src', 'usemap', 'lowsrc', 'highsrc' ),
503 'INPUT' => array( 'src', 'usemap', 'formaction' ),
504 'INS' => array( 'cite' ),
505 'LINK' => array( 'href' ),
506 'OBJECT' => array( 'classid', 'codebase', 'data', 'usemap' ),
507 'Q' => array( 'cite' ),
508 'SCRIPT' => array( 'src' ),
509 'SOURCE' => array( 'src' ),
510 'TRACK' => array( 'src' ),
511 'VIDEO' => array( 'poster', 'src' ),
512 );
513
514 /**
515 * @TODO: Either explicitly support these attributes, or explicitly drop support for
516 * handling their subsyntax. A generic URL matcher might be good enough.
517 */
518 public const HTML_ATTRIBUTES_WITH_SUBSYNTAX_TO_ACCEPT_RELATIVE_URLS_FROM = array(
519 '*' => array( 'style' ), // background(), background-image().
520 'APPLET' => array( 'archive' ),
521 'IMG' => array( 'srcset' ),
522 'META' => array( 'content' ),
523 'SOURCE' => array( 'srcset' ),
524 'OBJECT' => array( 'archive' ),
525 );
526
527 /**
528 * Also <style> and <script> tag content can contain URLs.
529 * <style> has specific syntax rules we can use for matching, but perhaps a generic matcher would be good enough?
530 *
531 * <style>
532 * #domID { background:url(https://mysite.com/wp-content/uploads/image.png) }
533 * </style>
534 *
535 * @TODO: Either explicitly support these tags, or explicitly drop support for
536 * handling their subsyntax. A generic URL matcher might be good enough.
537 */
538 public const HTML_TAGS_WITH_SUBSYNTAX_TO_ACCEPT_RELATIVE_URLS_FROM = array(
539 'STYLE',
540 'SCRIPT',
541 );
542 }
543