My ultimate goal is to consume the posts stored in a WordPress site from a mobile app (in React Native which shows the post inside a WebView component), and to do that I need to somehow get the sufficiently-fledged html content of the post without the WordPress theme related stuff like header, footer, sidebar.
What I mean with sufficiently-fledged html? Well, let me say something about the problem I encountered.
I tried retrieving the post html simply using get_post($postID)->post_content (and after I also tried to direct call the JSON WordPress REST API, but with same result). This html is not always well renderable by React due to some missing CSS and JavaScript, and this happens when I use some WordPress plugin to add custom content to a post. I realized this when I used premium WordPress plugin UniteGallery to add a photo-gallery to a post, and when React rendered the JSON version of the post it did not displayed the photo-galleries at all, instead it displayed e red message (within the normal HTML content):
UniteGallery css & scripts missing, check if your template includes wp_footer().
So I opened in a normal browser the full web page that display the same post, and I compared this HTML with the JSON-version one.
First I noticed the difference in size: web page is almost 2MB, the JSON-version is about 20KB. For this reason I would like to avoid such solutions where the (React) App should download the whole web page and after inject CSS to hide website theme related stuff like header, menu, sidebar and footer.
Instead I would like to prepare (server side) the html (not over-dimensioned) so that the app can use it as is.
I found that the huge HTML could be logically separated into 4 blocks:
- BLOCK1: a lot of theme related stuff: styles definitions (more than 70% of the content) and the unwanted theme header
- BLOCK2: the post content (almost identical to the JSON-version one)
- BLOCK3: unwanted sidebar of widgets and footer (theme template related stuff)
- BLOCK4: css imports, javascript imports and some javascript blocks.
Follows an extract of the ‘huge HTML’:
<!DOCTYPE html>
<html>
<!-- ********* BLOCK1 STARTS ********* -->
<head>
<title>Post Title</title>
<!-- several theme-related meta and css link tags -->
<!-- few theme-related javasdcript blocks and imports-->
<!-- REACT-RENDER REQUIREMENT no. 1: 2 jQuery imports -->
<script type='text/javascript' src='https://example.com/wp-includes/js/jquery/jquery.min.js?ver=3.5.1' id='jquery-core-js'></script>
<script type='text/javascript' src='https://example.com/wp-includes/js/jquery/jquery-migrate.min.js?ver=3.3.2' id='jquery-migrate-js'></script>
<style id="fusion-stylesheet-inline-css" type="text/css">
/* = = = = = > HUGE REACT-UNUSED theme-related CSS BLOCK < = = = = = */
</style>
</head>
<body>
<!-- SURELY UNWANTED HEADER related stuff -->
<!-- ********* BLOCK1 ENDS ********* -->
<!-- ********* BLOCK2 STARTS: THE_CONTENT ********* -->
<article id="post-1234" class="post post-1234 type-post status-publish">
<h1 class="entry-title">Post Title</h1>
<div class="video-shortcode">
<iframe title="YouTube video player" src="https://www.youtube.com/embed/Suib_DXOj0E?wmode=transparent&autoplay=0" width="800" height="450" allowfullscreen allow="autoplay; fullscreen"></iframe>
</div>
<div class="fusion-fullwidth" style="padding:0px;margin: 0px;border-width: 0px 0px 0px 0px;border-style:solid;">
<p><strong>Photo Gallery1 Title</strong></p>
<div id='unitegallery_1_1' class='unite-gallery' style='margin:0px auto;'>
<img alt="_FCO0020" src="" data-image="https://example.com/wp-content/uploads/FCO0020.jpg" data-thumb="https://example.com/wp-content/uploads/FCO0020-300x200.jpg" title="" style="display:none">
<img alt="_FCO0022" src="" data-image="https://example.com/wp-content/uploads/FCO0022.jpg" data-thumb="https://example.com/wp-content/uploads/FCO0022-300x200.jpg" title="" style="display:none">
<!-- FOLLOWS A LOT OF PICTURES OF THE PHOTO-GALLERY -->
</div>
<!-- Follows the Javascript block the check the presence of UniteGallery library, and display the red error -->
<script type='text/javascript'>
window.onload = function (e) {
if (typeof ugCheckForErrors == "undefined") {
document.getElementById("unitegallery_1_1").innerHTML =
"<span style='color:red'>Unite Gallery Error - gallery js and css files not included in the footer. Please make sure that wp_footer() function is added to your theme.</span>";
}
else { ugCheckForErrors("unitegallery_1_1", "jquery"); }
};
</script>
</div>
</article>
<!-- *** BLOCK2 ENDS *** -->
<!-- *** BLOCK3 STARTS *** -->
<aside id="sidebar" class="sidebar fusion-blogsidebar" style="float: right;">
<!-- SURELY UNWANTED SIDEBAR related stuff-->
</aside>
<div class="fusion-footer">
<!-- SURELY UNWANTED FOOTER related stuff-->
</div>
<!-- *** BLOCK3 ENDS *** -->
<!-- *** BLOCK4 STARTS *** -->
<div class="avada-footer-scripts">
<!-- some theme-related css link -->
<!-- REACT-RENDER REQUIREMENT no. 2: UniteGallery CSS link -->
<link rel='stylesheet' id='unite-gallery-css-css' href='https://example.com/wp-content/plugins/unitegallery/unitegallery-plugin/css/unite-gallery.css?ver=5.7.2' type='text/css' media='all' />
<!-- many theme-related imports and javascript blocks -->
<!-- REACT-RENDER REQUIREMENT no. 3: UniteGallery JS imports -->
<script type='text/javascript' src='https://example.com/wp-content/plugins/unitegallery/unitegallery-plugin/js/unitegallery.min.js?ver=5.7.2' id='unitegallery_main-js'></script>
<script type='text/javascript' src='https://example.com/wp-content/plugins/unitegallery/unitegallery-plugin/themes/tiles/ug-theme-tiles.js?ver=5.7.2' id='unitegallery_tiles_theme-js'></script>
<!-- REACT-RENDER REQUIREMENT no. 4: UniteGallery gallery unhiding -->
<script type='text/javascript'>
var ugapi1;
jQuery(document).ready(function () {
var objUGParams = {
gallery_theme: "tiles",
gallery_width: "100%",
tiles_type: "nested"
};
if (ugCheckForErrors('#unitegallery_1_1', 'cms'))
ugapi1 = jQuery('#unitegallery_1_1').unitegallery(objUGParams);
});
</script>
</div>
<!-- *** BLOCK4 ENDS *** -->
</body>
</html>
So I tried to append lines (CSS & JavaScript) that I highlighted with comments in the code above as REACT-RENDER REQUIREMENT to the JSON-version of the post (hard-coding those lines) and then React rendered properly the photo-galleries within the post. The photo-galleries were already there but hidden (with style display:none) and to be handled by CSS & JavaScript stuff that I manually added.
Note I added following required lines:
- 2 jQuery imports from BLOCK
- UniteGallery imports and javascript from BLOCK 4 while not all the css and javascripts present in BLOCK 4 are needed to obtain a working UniteGallery photo-gallery: most are website theme related stuff.
What I tried in order to systematically add missing plugins related stuff to the HTML is something like this:
ob_start(); // <- buffer following outputs
wp_head(); // <- output header stuff
$post = new \WP_Query('p ='. $postID);
if ($post->have_posts()) $post->the_post(); // <- output post content
wp_footer(); // <- output footer stuff
$full_post_content = ob_get_contents(); // get the output buffer
ob_end_clean(); // <- clear buffer and stop buffering
// -> save $full_post_content to DB table 'app_posts'
This way the content of the post is enriched with UniteGallery CSS & JavaScript imports, but is still missing jQuery imports (see BLOCK1 above) and UniteGallery JavaScript block that unhides the photo-gallery (see the end of BLOCK4 above) then the photo gallery in the post still is not displayed.
I encountered the problem using UniteGallery, but actually I suppose that any plugin that adds custom content into a post could potentially produce a post content not proper-renderable by React, if content of the post is retrieved by JSON-REST-API.
For this reason I am looking for such a way (for example within my custom WordPress plugin) to save an HTML version of posts that includes:
- light JSON-version of the content of the post
- CSS & JavaScripts needed to properly render such post in React, considering plugins involved in enriching post contents
and this is what I meant at the beginning of the question with 'sufficiently-fledged HTML content of the post'.
Obviously I don't know if there are built-in WordPress tool/API that can achieve this, but I am open to develop such custom plugin to easy the work of the user WordPress content manager.