@@ -275,21 +275,33 @@ protected function toPlainText(): string
275275 */
276276 public function render (bool $ blankIncludes = false ): string
277277 {
278- $ content = $ this ->page ->html ?? '' ;
278+ $ html = $ this ->page ->html ?? '' ;
279279
280- if (! config ( ' app.allow_content_scripts ' )) {
281- $ content = HtmlContentFilter:: removeScripts ( $ content ) ;
280+ if (empty ( $ html )) {
281+ return $ html ;
282282 }
283283
284- if ( $ blankIncludes ) {
285- $ content = $ this -> blankPageIncludes ( $ content );
286- } else {
287- for ($ includeDepth = 0 ; $ includeDepth < 3 ; $ includeDepth ++ ) {
288- $ content = $ this -> parsePageIncludes ( $ content ) ;
284+ $ doc = new HtmlDocument ( $ html );
285+
286+ $ contentProvider = function ( int $ id ) use ( $ blankIncludes ) {
287+ if ($ blankIncludes ) {
288+ return '' ;
289289 }
290+ return Page::visible ()->find ($ id )->html ?? '' ;
291+ };
292+
293+ $ parser = new PageIncludeParser ($ doc , $ contentProvider );
294+ $ nodesAdded = 1 ;
295+
296+ for ($ includeDepth = 0 ; $ includeDepth < 3 && $ nodesAdded !== 0 ; $ includeDepth ++) {
297+ $ nodesAdded = $ parser ->parse ();
298+ }
299+
300+ if (!config ('app.allow_content_scripts ' )) {
301+ HtmlContentFilter::removeScriptsFromDocument ($ doc );
290302 }
291303
292- return $ content ;
304+ return $ doc -> getBodyInnerHtml () ;
293305 }
294306
295307 /**
@@ -337,83 +349,4 @@ protected function headerNodesToLevelList(DOMNodeList $nodeList): array
337349
338350 return $ tree ->toArray ();
339351 }
340-
341- /**
342- * Remove any page include tags within the given HTML.
343- */
344- protected function blankPageIncludes (string $ html ): string
345- {
346- return preg_replace ("/{{@\s?([0-9].*?)}}/ " , '' , $ html );
347- }
348-
349- /**
350- * Parse any include tags "{{@<page_id>#section}}" to be part of the page.
351- */
352- protected function parsePageIncludes (string $ html ): string
353- {
354- $ matches = [];
355- preg_match_all ("/{{@\s?([0-9].*?)}}/ " , $ html , $ matches );
356-
357- foreach ($ matches [1 ] as $ index => $ includeId ) {
358- $ fullMatch = $ matches [0 ][$ index ];
359- $ splitInclude = explode ('# ' , $ includeId , 2 );
360-
361- // Get page id from reference
362- $ pageId = intval ($ splitInclude [0 ]);
363- if (is_nan ($ pageId )) {
364- continue ;
365- }
366-
367- // Find page to use, and default replacement to empty string for non-matches.
368- /** @var ?Page $matchedPage */
369- $ matchedPage = Page::visible ()->find ($ pageId );
370- $ replacement = '' ;
371-
372- if ($ matchedPage && count ($ splitInclude ) === 1 ) {
373- // If we only have page id, just insert all page html and continue.
374- $ replacement = $ matchedPage ->html ;
375- } elseif ($ matchedPage && count ($ splitInclude ) > 1 ) {
376- // Otherwise, if our include tag defines a section, load that specific content
377- $ innerContent = $ this ->fetchSectionOfPage ($ matchedPage , $ splitInclude [1 ]);
378- $ replacement = trim ($ innerContent );
379- }
380-
381- $ themeReplacement = Theme::dispatch (
382- ThemeEvents::PAGE_INCLUDE_PARSE ,
383- $ includeId ,
384- $ replacement ,
385- clone $ this ->page ,
386- $ matchedPage ? (clone $ matchedPage ) : null ,
387- );
388-
389- // Perform the content replacement
390- $ html = str_replace ($ fullMatch , $ themeReplacement ?? $ replacement , $ html );
391- }
392-
393- return $ html ;
394- }
395-
396- /**
397- * Fetch the content from a specific section of the given page.
398- */
399- protected function fetchSectionOfPage (Page $ page , string $ sectionId ): string
400- {
401- $ topLevelTags = ['table ' , 'ul ' , 'ol ' , 'pre ' ];
402- $ doc = new HtmlDocument ($ page ->html );
403-
404- // Search included content for the id given and blank out if not exists.
405- $ matchingElem = $ doc ->getElementById ($ sectionId );
406- if ($ matchingElem === null ) {
407- return '' ;
408- }
409-
410- // Otherwise replace the content with the found content
411- // Checks if the top-level wrapper should be included by matching on tag types
412- $ isTopLevel = in_array (strtolower ($ matchingElem ->nodeName ), $ topLevelTags );
413- if ($ isTopLevel ) {
414- return $ doc ->getNodeOuterHtml ($ matchingElem );
415- }
416-
417- return $ doc ->getNodeInnerHtml ($ matchingElem );
418- }
419352}
0 commit comments