';
}
$close_list();
return $html;
}
/**
* Heading ID as GitHub makes it, so README links such as
* `[Credits](#credits)` work in the tab too. Repeats get -1, -2...
*
* @param string $text Heading Markdown.
* @param array $ids IDs used so far (updated).
* @return string ID.
*/
private static function anchor($text, array &$ids) {
$text = preg_replace('/\[([^\]]+)\]\([^)]*\)/', '$1', $text);
$text = str_replace(array('`', '*'), '', $text);
$id = function_exists('mb_strtolower') ? mb_strtolower($text, 'UTF-8') : strtolower($text);
$id = preg_replace('/[^\p{L}\p{N}\s_-]/u', '', $id);
$id = preg_replace('/\s/u', '-', trim($id));
$base = '' === $id ? 'section' : $id;
$id = $base;
$n = 0;
while (isset($ids[$id])) {
$id = $base . '-' . (++$n);
}
$ids[$id] = true;
return $id;
}
/**
* An image from the plugin's folder, such as the banner at the top of
* README.md. Only relative paths to image files that exist are shown, so
* the tab never loads anything from another site.
*
* @param string $path Path relative to the plugin folder.
* @param string $alt Alternative text.
* @return string HTML, or '' for anything else.
*/
private static function image($path, $alt) {
if (!preg_match('#^[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*\.(?:svg|png|jpe?g|gif|webp)$#i', $path)) {
return '';
}
$file = WPSTARTER_DIR . $path;
if (!is_file($file)) {
return '';
}
// Width and height stop the page jumping while the image loads.
$size = '';
if ('svg' === strtolower(pathinfo($path, PATHINFO_EXTENSION))) {
$head = (string) file_get_contents($file, false, null, 0, 2048); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- local file.
if (preg_match('/