text($markdown);
// Process images if needed
if ($import_images) {
$html = self::process_images_in_html($html, $original_url);
}
// Convert HTML to blocks
return self::html_to_blocks($html);
}
/**
* Process images in HTML to import them to media library
*
* @param string $html HTML content
* @param string $original_url Original markdown URL for resolving relative paths
* @return string Processed HTML
*/
private static function process_images_in_html($html, $original_url = '') {
// Use DOMDocument to find and process images
$dom = new \DOMDocument();
@$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
$images = $dom->getElementsByTagName('img');
$updated = false;
// Process each image
foreach ($images as $img) {
$src = $img->getAttribute('src');
// Skip data URLs
if (strpos($src, 'data:') === 0) {
continue;
}
// Handle relative URLs
if (!filter_var($src, FILTER_VALIDATE_URL) && !empty($original_url)) {
// If the src doesn't start with http/https, it's likely a relative path
if (strpos($src, 'http') !== 0) {
$base_url = dirname($original_url) . '/';
$src = $base_url . ltrim($src, '/');
}
}
// Import external image
$attachment_id = PostCreator::import_external_image($src);
if ($attachment_id && !is_wp_error($attachment_id)) {
// Get new image URL
$new_src = wp_get_attachment_url($attachment_id);
if ($new_src) {
$img->setAttribute('src', $new_src);
$img->setAttribute('data-attachment-id', $attachment_id);
$updated = true;
}
}
}
if ($updated) {
$html = $dom->saveHTML();
}
return $html;
}
/**
* Convert HTML to Gutenberg blocks
*
* @param string $html HTML content
* @return string Gutenberg blocks content
*/
private static function html_to_blocks($html) {
// Create a DOM document
$dom = new \DOMDocument();
@$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
$xpath = new \DOMXPath($dom);
// Get the body element
$body = $dom->getElementsByTagName('body')->item(0);
// Process each child node of the body
$blocks = [];
if ($body) {
foreach ($body->childNodes as $node) {
if ($node->nodeType === XML_ELEMENT_NODE) {
$block = self::node_to_block($node, $xpath);
if ($block) {
$blocks[] = $block;
}
}
}
}
return implode("\n\n", $blocks);
}
/**
* Convert a DOM node to a Gutenberg block
*
* @param DOMNode $node The DOM node
* @param DOMXPath $xpath XPath object for querying
* @return string|null Gutenberg block or null if not convertible
*/
private static function node_to_block($node, $xpath) {
switch ($node->nodeName) {
case 'h1':
case 'h2':
case 'h3':
case 'h4':
case 'h5':
case 'h6':
$level = (int) substr($node->nodeName, 1);
return self::create_heading_block($node->textContent, $level);
case 'p':
// Check if paragraph contains only an image
$images = $node->getElementsByTagName('img');
if ($images->length === 1 && $node->childNodes->length === 1) {
$img = $images->item(0);
return self::create_image_block(
$img->getAttribute('src'),
$img->getAttribute('alt'),
$img->getAttribute('data-attachment-id')
);
} else {
// Regular paragraph with possible inline elements
$innerHTML = '';
foreach ($node->childNodes as $child) {
$innerHTML .= $node->ownerDocument->saveHTML($child);
}
return self::create_paragraph_block($innerHTML);
}
case 'ul':
case 'ol':
$items = [];
$list_items = $node->getElementsByTagName('li');
foreach ($list_items as $item) {
$innerHTML = '';
foreach ($item->childNodes as $child) {
$innerHTML .= $node->ownerDocument->saveHTML($child);
}
$items[] = $innerHTML;
}
return self::create_list_block($items, $node->nodeName === 'ol');
case 'blockquote':
$innerHTML = '';
foreach ($node->childNodes as $child) {
$innerHTML .= $node->ownerDocument->saveHTML($child);
}
return self::create_quote_block($innerHTML);
case 'pre':
$code = $node->getElementsByTagName('code')->item(0);
if ($code) {
return self::create_code_block($code->textContent);
}
return self::create_preformatted_block($node->textContent);
case 'hr':
return self::create_separator_block();
case 'table':
return self::create_table_block($node);
case 'img':
return self::create_image_block(
$node->getAttribute('src'),
$node->getAttribute('alt'),
$node->getAttribute('data-attachment-id')
);
default:
// For unsupported elements, convert to HTML block
return self::create_html_block($node->ownerDocument->saveHTML($node));
}
}
/**
* Create a heading block
*
* @param string $content Heading content
* @param int $level Heading level (1-6)
* @return string Gutenberg heading block
*/
private static function create_heading_block($content, $level = 2) {
return '' .
'
' . $content . '
' . ''; } /** * Create an image block * * @param string $src Image source URL * @param string $alt Image alt text * @param string $attachment_id WordPress attachment ID * @return string Gutenberg image block */ private static function create_image_block($src, $alt = '', $attachment_id = '') { $block_attrs = [ 'url' => $src, 'alt' => $alt ]; if ($attachment_id) { $block_attrs['id'] = (int) $attachment_id; // Get image dimensions if available $image_meta = wp_get_attachment_metadata($attachment_id); if ($image_meta && isset($image_meta['width']) && isset($image_meta['height'])) { $block_attrs['width'] = $image_meta['width']; $block_attrs['height'] = $image_meta['height']; $block_attrs['sizeSlug'] = 'full'; } // Get caption if available $attachment = get_post($attachment_id); if ($attachment && !empty($attachment->post_excerpt)) { $block_attrs['caption'] = $attachment->post_excerpt; } } // Create the image block with proper figure and figcaption if needed $figure_html = '' . ''; } /** * Create a code block * * @param string $content Code content * @return string Gutenberg code block */ private static function create_code_block($content) { return '' . '' . $content . '
' . esc_html($content) . '' .
'';
}
/**
* Create a preformatted block
*
* @param string $content Preformatted content
* @return string Gutenberg preformatted block
*/
private static function create_preformatted_block($content) {
return '' .
'' . esc_html($content) . '' . ''; } /** * Create a separator block * * @return string Gutenberg separator block */ private static function create_separator_block() { return '' . '
| ' . $cell->textContent . ' | '; } $html .= '
|---|
| ' . $cell->textContent . ' | '; } $html .= '