diff options
author | Juan José González <juanjosegzl@libreoffice.org> | 2024-01-06 13:39:28 -0600 |
---|---|---|
committer | Ilmari Lauhakangas <ilmari.lauhakangas@libreoffice.org> | 2024-01-07 09:24:23 +0100 |
commit | 5bb4a32e26d95b16cc49e6e1cef699a9db163718 (patch) | |
tree | fab6ac8f1ddbf8e3be73f2808e7fdd13643217a9 | |
parent | 8e7fb2d6946042247ccfa538320f32ec55a81e85 (diff) |
Abstract rendering code to a api endpoint, to eventually speed up rendering
Reorganized some code, moved js to folder, and rendering code to a file to be included
Overview:
api/helpers.php: utility functions I plan to use with API endpoints
api/xhp_to_xml.php: first endpoint, receives xhpdoc xml and return formatted html inside a json response
index.html: mostly formatting and add JS code to detect "rendering mode" to call the new endpoint asynchronously. Planning to do this exclusively async in future commits
renderer.php: I moved the existing code in index.html to its own file for the purpose of encapsulate it and rewrite it more easily
Change-Id: I95d46f5256419383b6a2e3d791781f60c9d4361e
Reviewed-on: https://gerrit.libreoffice.org/c/dev-tools/+/161723
Reviewed-by: Olivier Hallot <olivier.hallot@libreoffice.org>
Tested-by: Olivier Hallot <olivier.hallot@libreoffice.org>
-rw-r--r-- | help3/xhpeditor/api/helpers.php | 27 | ||||
-rw-r--r-- | help3/xhpeditor/api/xhp_to_xml.php | 30 | ||||
-rw-r--r-- | help3/xhpeditor/index.php | 174 | ||||
-rw-r--r-- | help3/xhpeditor/js/DisplayArea.js (renamed from help3/xhpeditor/DisplayArea.js) | 0 | ||||
-rw-r--r-- | help3/xhpeditor/js/autocomplete.js (renamed from help3/xhpeditor/autocomplete.js) | 0 | ||||
-rw-r--r-- | help3/xhpeditor/js/snippets.js (renamed from help3/xhpeditor/snippets.js) | 0 | ||||
-rw-r--r-- | help3/xhpeditor/js/xhp2html.js (renamed from help3/xhpeditor/xhp2html.js) | 0 | ||||
-rw-r--r-- | help3/xhpeditor/renderer.php | 111 | ||||
-rw-r--r-- | help3/xhpeditor/snippets.php | 29 | ||||
-rw-r--r-- | help3/xhpeditor/views/README | 1 | ||||
-rw-r--r-- | help3/xhpeditor/views/menu.php (renamed from help3/xhpeditor/menu.php) | 0 | ||||
-rw-r--r-- | help3/xhpeditor/views/toolbar.php (renamed from help3/xhpeditor/toolbar.php) | 0 |
12 files changed, 224 insertions, 148 deletions
diff --git a/help3/xhpeditor/api/helpers.php b/help3/xhpeditor/api/helpers.php new file mode 100644 index 00000000..523f1012 --- /dev/null +++ b/help3/xhpeditor/api/helpers.php @@ -0,0 +1,27 @@ +<?php + +function get_method() { + return $_SERVER["REQUEST_METHOD"]; +} + +function get_data() { + return array_merge( + $_GET, + empty($_POST) ? [] : $_POST, + (array) json_decode(file_get_contents('php://input'), true) + ); +} + + +function respond($response, $code=200) { + http_response_code($code); + header('Content-Type: application/json'); + die(json_encode($response)); +} + +function is_not_ajax () { + return ( + empty($_SERVER['HTTP_X_REQUESTED_WITH']) + || strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) !== 'xmlhttprequest' + ); +} diff --git a/help3/xhpeditor/api/xhp_to_xml.php b/help3/xhpeditor/api/xhp_to_xml.php new file mode 100644 index 00000000..73e27857 --- /dev/null +++ b/help3/xhpeditor/api/xhp_to_xml.php @@ -0,0 +1,30 @@ +<?php +require_once './helpers.php'; +require '../config.php'; + +try { + $method = get_method(); + $data = get_data(); + + if (!isset($data['xhpdoc'])) { + respond(['message' => 'XHP is required'], 400); + } + + $xhp = $data['xhpdoc']; + + $xml = new DOMDocument(); + $xml->loadXML($xhp); + $xsl = new DOMDocument; + $xsl->load('../ed_transform.xsl'); + $proc = new XSLTProcessor(); + $proc->setParameter("", "root", $CONFIG["help_path"]); + $proc->setParameter("", "productname", $CONFIG["productname"]); + $proc->setParameter("", "iconpath", $CONFIG["icon_path"]); + $proc->importStyleSheet($xsl); + + $output = @$proc->transformToXml($xml); + respond(['preview' => $output]); +} +catch (Exception $e) { + respond(['message' => 'Unexpected error'], 500); +} diff --git a/help3/xhpeditor/index.php b/help3/xhpeditor/index.php index 1af632e5..b8647d3a 100644 --- a/help3/xhpeditor/index.php +++ b/help3/xhpeditor/index.php @@ -7,18 +7,20 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. --> <?php -require_once './config.php'; -require_once './snippets.php'; + $xhp = isset($_POST["xhpdoc"]) ? $_POST["xhpdoc"] : null; if ($xhp) { $xhp_filename = simplexml_load_string($xhp)->xpath("//filename"); } + +$label_editing = isset($xhp_filename) ? "Editing: {$xhp_filename[0]}" : " "; +$escaped_xhp_source = htmlspecialchars($xhp, ENT_NOQUOTES); ?> <html> -<head> -<meta charset="utf-8"/> -<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"> + <head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"> <title>LibreOffice XHP Editor</title> <link rel="shortcut icon" href="favicon.ico"/> <link type="text/css" rel="stylesheet" href="cm/lib/codemirror.css"> @@ -49,123 +51,57 @@ if ($xhp) { <script type="application/javascript" src="cm/addon/scroll/annotatescrollbar.js"></script> <script type="application/javascript" src="helpcontent2/help3xsl/prism.js"></script> - <script type="application/javascript" src="autocomplete.js"></script> - <script type="application/javascript" src="snippets.js"></script> - <script type="application/javascript" src="DisplayArea.js"></script> - <script type="application/javascript" src="xhp2html.js" defer></script> -</head> + <script type="application/javascript" src="js/autocomplete.js"></script> + <script type="application/javascript" src="js/snippets.js"></script> + <script type="application/javascript" src="js/DisplayArea.js"></script> + <script type="application/javascript" src="js/xhp2html.js" defer></script> + + <script type="text/javascript"> + const is_render_mode = '<?=isset($_POST["render_page"])?1:0?>'; + const xhpdoc = `<?=$_POST["xhpdoc"]?>`; + + // Trigger this snippet without reloading page + if (is_render_mode == 1) { + fetch('api/xhp_to_xml.php', { + method: 'POST', + headers: { + 'X-Requested-With': 'XMLHttpRequest', + }, + body: JSON.stringify({ + xhpdoc + }) + }).then(response => response.json()) + .then(data => { + document.getElementById('renderedpage').innerHTML = data.preview; + }); + } + </script> + + </head> + + <body style="font-family:sans-serif;"> + + <div id="editorpageheader"> + <header> + <img class="logo" alt="LibreOffice" src="logo.png" /> + <h1>LibreOffice Documentation XHP Editor</h1> + <p> + <?=$label_editing?> + </p> + </header> + <?php include './views/menu.php';?> + <?php include './views/toolbar.php'; ?> + </div> -<body style="font-family:sans-serif;"> - <div id="editorpageheader"> - <header> - <img class="logo" src="logo.png" /> - <h1>LibreOffice Documentation XHP Editor</h1> - <p> - <?php - echo isset($xhp_filename) ? "Editing: {$xhp_filename[0]}" : " "; - ?> - </p> - </header> - <?php include './menu.php';?> - <?php include './toolbar.php'; ?> - </div> <div id="editortextarea"> - <form id="CMtextarea" method="post" action="index.php"> - <textarea id="xhpeditor" name="xhpdoc" form="CMtextarea"><?php echo htmlspecialchars($xhp,ENT_NOQUOTES);?></textarea> - </form> + <form id="CMtextarea" method="post" action="index.php"> + <?php // Print the content with no new lines to prevent rendering errors ?> + <textarea id="xhpeditor" name="xhpdoc" form="CMtextarea"><?=$escaped_xhp_source?></textarea> + </form> </div> - <?php - if (isset($_POST["render_page"])) { - echo '<div id="renderedpageheader">'; - echo '<div class="buttonrow"><div class="systembuttons">System: '; - $opSys = array("MAC", "WIN", "UNIX"); - foreach ($opSys as $value) { - echo '<input type="radio" name="sys" id="' . $value . '" onclick="setSystemSpan(\''.$value.'\')" /><label for="' . $value . '">'.$value.'</label> '; - } - echo '</div><div class="applbuttons">Module: '; - $appModule = array("WRITER", "CALC", "IMPRESS", "DRAW", "BASE", "MATH", "CHART"); - foreach ($appModule as $value){ - echo '<input type="radio" name="app" onclick="setApplSpan(\''.$value.'\')" id="'. $value .'"><label for="'. $value .'">'.$value.'</label> '; - } - echo '</div></div></div><div id="renderedpage">'; - $xml = new DOMDocument(); - $xml->loadXML($xhp); - $xsl = new DOMDocument; - $xsl->load('ed_transform.xsl'); - $proc = new XSLTProcessor(); - $proc->setParameter("","root",$CONFIG["help_path"]); - $proc->setParameter("","productname",$CONFIG["productname"]); - $proc->setParameter("","iconpath",$CONFIG["icon_path"]); - $proc->importStyleSheet($xsl); - echo @$proc->transformToXml($xml); - echo "</div>"; - }elseif (isset($_POST["check_xhp"])) { - libxml_use_internal_errors(true); - libxml_clear_errors(); - $root = 'helpdocument'; - $old = new DOMDocument; - echo '<div id="renderedpageheader"><h2>Help File Verification: '.$xhp_filename[0]; - echo '</h2></div>'; - echo '<div id="renderedpage"><h3>Check XML Formation</h3>'; - if ( !$old->loadXML($xhp) ) { - $errors = libxml_get_errors(); - echo '<p class="bug">The XML is malformed!</p>'; - foreach ($errors as $error) { - echo display_xml_error($error, explode("\n", $old->saveXML())); - } - libxml_clear_errors(); - }else{ - echo "<p>No XML errors found!</p>"; - $creator = new DOMImplementation; - $doctype = $creator->createDocumentType($root, null, 'xmlhelp.dtd'); - $new = $creator->createDocument(null, null, $doctype); - $new->encoding = "utf-8"; + <?php include './renderer.php' ?> + + </body> - $oldNode = $old->getElementsByTagName($root)->item(0); - $newNode = $new->importNode($oldNode, true); - $new->appendChild($newNode); - libxml_clear_errors(); - echo '<h3>Check XML Document Type Definition:</h3>'; - if (!$new->validate()) { - echo '<p class="bug">This document does not verify the DTD and is <b>NOT VALID!</b></p>'; - $errors = libxml_get_errors(); - foreach ($errors as $error) { - echo display_xml_error($error, explode("\n", $new->saveXML())); - } - libxml_clear_errors(); - }else{ - echo '<p>No DTD errors found!</p>'; - }; - echo "<h3>Check duplicated id= :</h3>"; - $tags_id_uniq = array('paragraph','note','warning','tip','h1','h2','h3','h4','h5','h6'); - $xmlarray = simplexml_load_string($xhp); - $i=0; - foreach($tags_id_uniq as $tag_uniq) { - foreach ($xmlarray->xpath("//$tag_uniq") as $tag){ - $idarray[$i] = $tag['id']; - ++$i; - } - } - $dupped_array = array_values(array_unique(array_diff_key($idarray, array_unique($idarray)))); - if (count($dupped_array) > 0){ - echo '<p class="bug">Found duplicated id= attributes:</p>'; - foreach($dupped_array as $dup) { - echo "<p>$dup</p>"; - } - }else{ - echo "<p>No duplicate id= found.</p></div>"; - } - } - }elseif (isset($_POST["get_patch"])) { - echo '<div id="renderedpageheader">'; - echo '<h2>Get Patch:</h2>'; - echo "</div>"; - } else { - echo '<div id="renderedpageheader">'; - include 'views/empty_preview.php'; - echo "</div>"; - }; - ?> -</body> </html> diff --git a/help3/xhpeditor/DisplayArea.js b/help3/xhpeditor/js/DisplayArea.js index 20bbec8a..20bbec8a 100644 --- a/help3/xhpeditor/DisplayArea.js +++ b/help3/xhpeditor/js/DisplayArea.js diff --git a/help3/xhpeditor/autocomplete.js b/help3/xhpeditor/js/autocomplete.js index 2af035fc..2af035fc 100644 --- a/help3/xhpeditor/autocomplete.js +++ b/help3/xhpeditor/js/autocomplete.js diff --git a/help3/xhpeditor/snippets.js b/help3/xhpeditor/js/snippets.js index fd1564b8..fd1564b8 100644 --- a/help3/xhpeditor/snippets.js +++ b/help3/xhpeditor/js/snippets.js diff --git a/help3/xhpeditor/xhp2html.js b/help3/xhpeditor/js/xhp2html.js index 4ce2886f..4ce2886f 100644 --- a/help3/xhpeditor/xhp2html.js +++ b/help3/xhpeditor/js/xhp2html.js diff --git a/help3/xhpeditor/renderer.php b/help3/xhpeditor/renderer.php new file mode 100644 index 00000000..45a63c24 --- /dev/null +++ b/help3/xhpeditor/renderer.php @@ -0,0 +1,111 @@ +<?php +function display_xml_error($error, $xml) +{ + $return = '<p>'.$xml[$error->line - 1] . '<br>'; +// $return .= str_repeat('-', $error->column) . "^<br>"; + + switch ($error->level) { + case LIBXML_ERR_WARNING: + $return .= "Warning $error->code: "; + break; + case LIBXML_ERR_ERROR: + $return .= "Error $error->code: "; + break; + case LIBXML_ERR_FATAL: + $return .= "Fatal Error $error->code: "; + break; + } + + $return .= trim($error->message) . + "<br> Line: $error->line" . + "<br> Column: $error->column"; + + if ($error->file) { + $return .= "<br> File: " . $error->file; + } + + return $return . "<br>--------------------------------------------</p>"; +} + +if (isset($_POST["render_page"])) { + echo '<div id="renderedpageheader">'; + echo '<div class="buttonrow"><div class="systembuttons">System: '; + $opSys = array("MAC", "WIN", "UNIX"); + foreach ($opSys as $value) { + echo '<input type="radio" name="sys" id="' . $value . '" onclick="setSystemSpan(\''.$value.'\')" /><label for="' . $value . '">'.$value.'</label> '; + } + echo '</div><div class="applbuttons">Module: '; + $appModule = array("WRITER", "CALC", "IMPRESS", "DRAW", "BASE", "MATH", "CHART"); + foreach ($appModule as $value){ + echo '<input type="radio" name="app" onclick="setApplSpan(\''.$value.'\')" id="'. $value .'"><label for="'. $value .'">'.$value.'</label> '; + } + echo '</div></div></div><div id="renderedpage">'; + echo "</div>"; +}elseif (isset($_POST["check_xhp"])) { + libxml_use_internal_errors(true); + libxml_clear_errors(); + $root = 'helpdocument'; + $old = new DOMDocument; + + echo '<div id="renderedpageheader"><h2>Help File Verification: '.$xhp_filename[0]; + echo '</h2></div>'; + echo '<div id="renderedpage"><h3>Check XML Formation</h3>'; + if ( !$old->loadXML($xhp) ) { + $errors = libxml_get_errors(); + echo '<p class="bug">The XML is malformed!</p>'; + foreach ($errors as $error) { + echo display_xml_error($error, explode("\n", $old->saveXML())); + } + libxml_clear_errors(); + }else{ + echo "<p>No XML errors found!</p>"; + $creator = new DOMImplementation; + $doctype = $creator->createDocumentType($root, null, 'xmlhelp.dtd'); + $new = $creator->createDocument(null, null, $doctype); + $new->encoding = "utf-8"; + + $oldNode = $old->getElementsByTagName($root)->item(0); + $newNode = $new->importNode($oldNode, true); + $new->appendChild($newNode); + libxml_clear_errors(); + echo '<h3>Check XML Document Type Definition:</h3>'; + if (!$new->validate()) { + echo '<p class="bug">This document does not verify the DTD and is <b>NOT VALID!</b></p>'; + $errors = libxml_get_errors(); + foreach ($errors as $error) { + echo display_xml_error($error, explode("\n", $new->saveXML())); + } + libxml_clear_errors(); + }else{ + echo '<p>No DTD errors found!</p>'; + }; + echo "<h3>Check duplicated id= :</h3>"; + $tags_id_uniq = array('paragraph','note','warning','tip','h1','h2','h3','h4','h5','h6'); + $xmlarray = simplexml_load_string($xhp); + $i=0; + foreach($tags_id_uniq as $tag_uniq) { + foreach ($xmlarray->xpath("//$tag_uniq") as $tag){ + $idarray[$i] = $tag['id']; + ++$i; + } + } + $dupped_array = array_values(array_unique(array_diff_key($idarray, array_unique($idarray)))); + if (count($dupped_array) > 0){ + echo '<p class="bug">Found duplicated id= attributes:</p>'; + foreach($dupped_array as $dup) { + echo "<p>$dup</p>"; + } + }else{ + echo "<p>No duplicate id= found.</p></div>"; + } + } +}elseif (isset($_POST["get_patch"])) { + echo '<div id="renderedpageheader">'; + echo '<h2>Get Patch:</h2>'; + echo "</div>"; +} else { + echo '<div id="renderedpageheader">'; + include 'views/empty_preview.php'; + echo "</div>"; +}; +?> diff --git a/help3/xhpeditor/snippets.php b/help3/xhpeditor/snippets.php deleted file mode 100644 index e9b2ddf0..00000000 --- a/help3/xhpeditor/snippets.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php -function display_xml_error($error, $xml) -{ - $return = '<p>'.$xml[$error->line - 1] . '<br>'; -// $return .= str_repeat('-', $error->column) . "^<br>"; - - switch ($error->level) { - case LIBXML_ERR_WARNING: - $return .= "Warning $error->code: "; - break; - case LIBXML_ERR_ERROR: - $return .= "Error $error->code: "; - break; - case LIBXML_ERR_FATAL: - $return .= "Fatal Error $error->code: "; - break; - } - - $return .= trim($error->message) . - "<br> Line: $error->line" . - "<br> Column: $error->column"; - - if ($error->file) { - $return .= "<br> File: " . $error->file; - } - - return $return . "<br>--------------------------------------------</p>"; -} -?> diff --git a/help3/xhpeditor/views/README b/help3/xhpeditor/views/README new file mode 100644 index 00000000..b352073e --- /dev/null +++ b/help3/xhpeditor/views/README @@ -0,0 +1 @@ +Reusable piece of UI with no logic
\ No newline at end of file diff --git a/help3/xhpeditor/menu.php b/help3/xhpeditor/views/menu.php index 8725dd19..8725dd19 100644 --- a/help3/xhpeditor/menu.php +++ b/help3/xhpeditor/views/menu.php diff --git a/help3/xhpeditor/toolbar.php b/help3/xhpeditor/views/toolbar.php index c272b477..c272b477 100644 --- a/help3/xhpeditor/toolbar.php +++ b/help3/xhpeditor/views/toolbar.php |