summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan José González <juanjosegzl@libreoffice.org>2024-01-14 11:15:12 -0600
committerOlivier Hallot <olivier.hallot@libreoffice.org>2024-01-16 20:37:14 +0100
commitdd303175ab0882d9e4f41773a1342f51250cb295 (patch)
tree9d8df817ec6e88f5b89c13034b1e55488d1c450b
parentb347baf1eaefc0c5538ec6a4ea6b4a5ba2f8a895 (diff)
Use the new endpoint to check document, render error messages with JS
Change-Id: I8e0a9ccd45270cd10fcd10fdd1d9a6b4745f8f3d Reviewed-on: https://gerrit.libreoffice.org/c/dev-tools/+/162051 Reviewed-by: Olivier Hallot <olivier.hallot@libreoffice.org> Tested-by: Olivier Hallot <olivier.hallot@libreoffice.org>
-rw-r--r--help3/xhpeditor/.gitignore1
-rw-r--r--help3/xhpeditor/css/DisplayArea.css (renamed from help3/xhpeditor/DisplayArea.css)0
-rw-r--r--help3/xhpeditor/css/bootstrap-icons.min.css (renamed from help3/xhpeditor/bootstrap-icons.min.css)0
-rw-r--r--help3/xhpeditor/css/fonts/bootstrap-icons.woff (renamed from help3/xhpeditor/fonts/bootstrap-icons.woff)bin176088 -> 176088 bytes
-rw-r--r--help3/xhpeditor/css/fonts/bootstrap-icons.woff2 (renamed from help3/xhpeditor/fonts/bootstrap-icons.woff2)bin130648 -> 130648 bytes
-rw-r--r--help3/xhpeditor/css/xhpeditor.css (renamed from help3/xhpeditor/xhpeditor.css)36
-rw-r--r--help3/xhpeditor/index.php114
-rw-r--r--help3/xhpeditor/js/snippets.js99
-rw-r--r--help3/xhpeditor/js/xhp2html.js37
-rw-r--r--help3/xhpeditor/renderer.php19
-rw-r--r--help3/xhpeditor/views/menu.php6
11 files changed, 249 insertions, 63 deletions
diff --git a/help3/xhpeditor/.gitignore b/help3/xhpeditor/.gitignore
new file mode 100644
index 00000000..279f9b57
--- /dev/null
+++ b/help3/xhpeditor/.gitignore
@@ -0,0 +1 @@
+xmlhelp.dtd
diff --git a/help3/xhpeditor/DisplayArea.css b/help3/xhpeditor/css/DisplayArea.css
index c6351c0f..c6351c0f 100644
--- a/help3/xhpeditor/DisplayArea.css
+++ b/help3/xhpeditor/css/DisplayArea.css
diff --git a/help3/xhpeditor/bootstrap-icons.min.css b/help3/xhpeditor/css/bootstrap-icons.min.css
index b882fd5a..b882fd5a 100644
--- a/help3/xhpeditor/bootstrap-icons.min.css
+++ b/help3/xhpeditor/css/bootstrap-icons.min.css
diff --git a/help3/xhpeditor/fonts/bootstrap-icons.woff b/help3/xhpeditor/css/fonts/bootstrap-icons.woff
index ae24c650..ae24c650 100644
--- a/help3/xhpeditor/fonts/bootstrap-icons.woff
+++ b/help3/xhpeditor/css/fonts/bootstrap-icons.woff
Binary files differ
diff --git a/help3/xhpeditor/fonts/bootstrap-icons.woff2 b/help3/xhpeditor/css/fonts/bootstrap-icons.woff2
index fff9d0cf..fff9d0cf 100644
--- a/help3/xhpeditor/fonts/bootstrap-icons.woff2
+++ b/help3/xhpeditor/css/fonts/bootstrap-icons.woff2
Binary files differ
diff --git a/help3/xhpeditor/xhpeditor.css b/help3/xhpeditor/css/xhpeditor.css
index c4b91e49..e14ea532 100644
--- a/help3/xhpeditor/xhpeditor.css
+++ b/help3/xhpeditor/css/xhpeditor.css
@@ -133,7 +133,6 @@ ol, ul {
position: sticky;
top:0px;
margin: 0px;
- background: AliceBlue;
}
#renderedpage {
@@ -141,7 +140,6 @@ ol, ul {
padding: 3px;
margin: 0px;
overflow-y:auto;
- background: AliceBlue;
display:inline-block;
}
.buttonrow{
@@ -253,3 +251,37 @@ div.card div.card-body {
border-radius: 0 0 6px 6px;
background-color: #fefefe;
}
+
+/* Check mode results */
+div#renderedpage {
+ padding: 12px;
+}
+
+div#renderedpage div.no-error-message {
+ padding: 6px;
+ border-left: 4px solid green;
+}
+
+div#renderedpage div.error-message {
+ padding: 6px;
+ border-left: 4px solid gray;
+ margin-bottom: 12px;
+}
+
+div#renderedpage div.severity-fatal {
+ border-left-color: red;
+ background-color: rgba(255,0,0,0.1);
+}
+
+div#renderedpage div.severity-error {
+ border-left-color: red;
+}
+
+div#renderedpage div.severity-warning {
+ border-left-color: red;
+}
+
+div#renderedpage span.goto {
+ cursor: pointer;
+ color: blue;
+}
diff --git a/help3/xhpeditor/index.php b/help3/xhpeditor/index.php
index c3ac4a97..b72b3dbc 100644
--- a/help3/xhpeditor/index.php
+++ b/help3/xhpeditor/index.php
@@ -25,16 +25,16 @@ $escaped_xhp_source = htmlspecialchars($xhp, ENT_NOQUOTES);
<meta name="description" content="Online editor to create and modify XHP help files for LibreOffice Suite. The XHP editor includes a syntax validator and preview side by side." />
<link rel="icon" href="favicon.ico"/>
- <link type="text/css" rel="stylesheet" href="cm/lib/codemirror.css">
- <link type="text/css" rel="stylesheet" href="cm/addon/hint/show-hint.css">
<link type="text/css" rel="stylesheet" href="cm/addon/dialog/dialog.css">
<link type="text/css" rel="stylesheet" href="cm/addon/display/fullscreen.css">
- <link type="text/css" rel="stylesheet" href="xhpeditor.css">
+ <link type="text/css" rel="stylesheet" href="cm/addon/hint/show-hint.css">
+ <link type="text/css" rel="stylesheet" href="cm/addon/search/matchesonscrollbar.css">
+ <link type="text/css" rel="stylesheet" href="cm/lib/codemirror.css">
+ <link type="text/css" rel="stylesheet" href="css/DisplayArea.css">
+ <link type="text/css" rel="stylesheet" href="css/bootstrap-icons.min.css">
+ <link type="text/css" rel="stylesheet" href="css/xhpeditor.css">
<link type="text/css" rel="stylesheet" href="helpcontent2/help3xsl/normalize.css">
<link type="text/css" rel="stylesheet" href="helpcontent2/help3xsl/prism.css">
- <link type="text/css" rel="stylesheet" href="DisplayArea.css">
- <link type="text/css" rel="stylesheet" href="cm/addon/search/matchesonscrollbar.css">
- <link rel="stylesheet" href="bootstrap-icons.min.css">
<script type="application/javascript" src="cm/lib/codemirror.js"></script>
<script type="application/javascript" src="cm/mode/xml/xml.js"></script>
@@ -51,6 +51,7 @@ $escaped_xhp_source = htmlspecialchars($xhp, ENT_NOQUOTES);
<script type="application/javascript" src="cm/addon/search/matchesonscrollbar.js"></script>
<script type="application/javascript" src="cm/addon/display/fullscreen.js"></script>
<script type="application/javascript" src="cm/addon/scroll/annotatescrollbar.js"></script>
+ <script type="application/javascript" src="cm/addon/selection/active-line.js"></script>
<script type="application/javascript" src="helpcontent2/help3xsl/prism.js"></script>
<script type="application/javascript" src="js/autocomplete.js"></script>
@@ -59,24 +60,44 @@ $escaped_xhp_source = htmlspecialchars($xhp, ENT_NOQUOTES);
<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;
- });
+ function show_render() {
+ 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) {
+ document.getElementById("render_mode").style.display = "block";
+ 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;
+ });
+ }
}
+
+ window.EDITOR_MODE = {
+ EMPTY: 'empty',
+ RENDER: 'render',
+ CHECK: 'check',
+ };
+
+ function showSection(current_mode) {
+ document.querySelectorAll('section.preview-section').forEach(s=>s.style.display = 'none');
+ document.querySelector(`#${current_mode}-mode`).style.display = 'block';
+ document.getElementById('renderedpage').innerHTML = "";
+ }
+
+ document.addEventListener("DOMContentLoaded", (event) => {
+ const current_mode = window.mode || EDITOR_MODE.EMPTY
+ showSection(current_mode);
+ });
</script>
</head>
@@ -87,7 +108,7 @@ $escaped_xhp_source = htmlspecialchars($xhp, ENT_NOQUOTES);
<header>
<img class="logo" alt="LibreOffice" src="logo.png" />
<h1>LibreOffice Help XHP Editor</h1>
- <p>
+ <p id="editing_filename">
<?=$label_editing?>
</p>
</header>
@@ -102,8 +123,49 @@ $escaped_xhp_source = htmlspecialchars($xhp, ENT_NOQUOTES);
</form>
</div>
- <?php include './renderer.php' ?>
+ <div id="renderedpageheader">
+ <section id="empty-mode" class="preview-section">
+ <?php include "views/empty_preview.php" ?>
+ </section>
+ <section id="render-mode" class="preview-section">
+ <div class="buttonrow">
+ <div class="systembuttons">
+ System:
+ <input type="radio" name="sys" id="MAC" onclick="setSystemSpan('MAC')">
+ <label for="MAC">MAC</label>
+ <input type="radio" name="sys" id="WIN" onclick="setSystemSpan('WIN')">
+ <label for="WIN">WIN</label>
+ <input type="radio" name="sys" id="UNIX" onclick="setSystemSpan('UNIX')">
+ <label for="UNIX">UNIX</label>
+ </div>
+
+ <div class="applbuttons">
+ Module:
+ <input type="radio" name="app" onclick="setApplSpan('WRITER')" id="WRITER">
+ <label for="WRITER">WRITER</label>
+ <input type="radio" name="app" onclick="setApplSpan('CALC')" id="CALC">
+ <label for="CALC">CALC</label>
+ <input type="radio" name="app" onclick="setApplSpan('IMPRESS')" id="IMPRESS">
+ <label for="IMPRESS">IMPRESS</label>
+ <input type="radio" name="app" onclick="setApplSpan('DRAW')" id="DRAW">
+ <label for="DRAW">DRAW</label>
+ <input type="radio" name="app" onclick="setApplSpan('BASE')" id="BASE">
+ <label for="BASE">BASE</label>
+ <input type="radio" name="app" onclick="setApplSpan('MATH')" id="MATH">
+ <label for="MATH">MATH</label>
+ <input type="radio" name="app" onclick="setApplSpan('CHART')" id="CHART">
+ <label for="CHART">CHART</label>
+ </div>
+ </div>
+ </section>
- </body>
+ <section id="check-mode" class="preview-section">
+ <h2>Help File Verification: <?=$xhp_filename?></h2>
+ </section>
+ </div>
+
+ <div id="renderedpage">
+ </div>
+</body>
</html>
diff --git a/help3/xhpeditor/js/snippets.js b/help3/xhpeditor/js/snippets.js
index fd1564b8..f2d4303e 100644
--- a/help3/xhpeditor/js/snippets.js
+++ b/help3/xhpeditor/js/snippets.js
@@ -246,4 +246,103 @@ function lower(x) { return x.toLowerCase(); }
function random(x) {var d = new Date(); return x +'_id'+(Math.floor(Math.random() * 100) + 1) + d.getTime(); }
function helpFile() {var d = document.url(); var t = d.search("text/"); return d.substr(t); }
+function renderXHP() {
+ const xhpdoc = window.editor.getValue();
+
+ window.mode = window.EDITOR_MODE.RENDER;
+ showSection(window.EDITOR_MODE.RENDER);
+
+ 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;
+ });
+}
+
+function renderCheckErrors(errors) {
+ const renderedPage = document.getElementById('renderedpage');
+ renderedPage.innerHTML = "";
+
+ const noErrors = (errors.xhp_errors.length + errors.duplicated_ids.length) === 0;
+ if (noErrors) {
+ const noErrorsMessage = `
+ <div class="no-error-message">
+ <p><strong>No errors found</strong></p>
+ <p>No XML, DTD or duplicated id errors.</p>
+ </div>
+ `;
+
+ renderedPage.innerHTML += noErrorsMessage;
+ return;
+ }
+
+ const SEVERITY = {
+ 1: 'warning',
+ 2: 'error',
+ 3: 'fatal',
+ }
+ if (errors.xhp_errors.length > 0) {
+ for (const xhpError of errors.xhp_errors) {
+ console.log(xhpError);
+ const errorMessage = `
+ <div class="error-message severity-${SEVERITY[xhpError.level]}">
+ <p><strong>${xhpError.message}</strong></p>
+ <span>Line: ${xhpError.line}. Column: ${xhpError.column}.</span>
+ <span class="goto" onclick="goToLine(${xhpError.line}, ${xhpError.column})">Go to line</span>
+ </div>
+ `.trim();
+ renderedPage.innerHTML += errorMessage;
+ }
+ }
+ if (errors.duplicated_ids.length > 0) {
+ // render duplicated ids
+ const duplicatedTitle = document.createElement('p');
+ duplicatedTitle.appendChild(
+ document.createTextNode('Found duplicated id attributes')
+ );
+ renderedPage.appendChild(duplicatedTitle);
+
+ const dupList = document.createElement('ol');
+ let dupItem = null;
+ for (const dupError of errors.duplicated_ids) {
+ dupItem = document.createElement('li');
+ dupItem.appendChild(
+ document.createTextNode(dupError[0])
+ )
+ dupList.appendChild(dupItem);
+ }
+
+ renderedPage.appendChild(dupList);
+ }
+}
+
+function checkXHP() {
+ const xhpdoc = window.editor.getValue();
+
+ window.mode = window.EDITOR_MODE.CHECK;
+ showSection(window.mode);
+
+ fetch('api/check_xhp.php', {
+ method: 'POST',
+ headers: {
+ 'X-Requested-With': 'XMLHttpRequest',
+ },
+ body: JSON.stringify({
+ xhpdoc
+ })
+ }).then(
+ response => response.json()
+ ).then(data => {
+ renderCheckErrors(data.errors);
+ });
+
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/help3/xhpeditor/js/xhp2html.js b/help3/xhpeditor/js/xhp2html.js
index 4ce2886f..27d5076f 100644
--- a/help3/xhpeditor/js/xhp2html.js
+++ b/help3/xhpeditor/js/xhp2html.js
@@ -12,6 +12,7 @@
// Codemirror configuration
var editor = CodeMirror.fromTextArea(document.getElementById("xhpeditor"), {
+ styleActiveLine: { nonEmpty: true },
lineNumbers: true,
theme: "default",
mode: "xml",
@@ -41,21 +42,23 @@ const height = window.innerHeight - document.getElementById('editorpageheader').
editor.setSize(null, height);
function readSingleFile(e) {
- var file = e.target.files[0];
+ const file = e.target.files[0];
- if (!file) {
- return;
- }
- var reader = new FileReader();
- reader.onload = function(e) {
- var contents = e.target.result;
- editor.doc.setValue(contents);
- };
+ if (!file) {
+ return;
+ }
+
+ const reader = new FileReader();
+ reader.onload = function(e) {
+ var contents = e.target.result;
+ document.getElementById('editing_filename').textContent = `Editing ${file.name}`;
+ editor.doc.setValue(contents);
+ };
- // Refresh preview when load hasd ended
- reader.onloadend = function(e) {
- document.getElementById("render_page").click();
- }
+ // Refresh preview when load hasd ended
+ reader.onloadend = function(e) {
+ document.getElementById("render_page").click();
+ }
reader.readAsText(file);
}
@@ -90,3 +93,11 @@ function downloadFile(data, filename, type) {
}, 0);
}
}
+
+function goToLine(line, ch) {
+ var t = editor.charCoords({line: line-1, ch: 0}, "local").top;
+ editor.setCursor({line: line-1, ch});
+ editor.focus();
+ var middleHeight = editor.getScrollerElement().offsetHeight / 2;
+ editor.scrollTo(null, t - middleHeight - 5);
+}
diff --git a/help3/xhpeditor/renderer.php b/help3/xhpeditor/renderer.php
index 45a63c24..a576d70c 100644
--- a/help3/xhpeditor/renderer.php
+++ b/help3/xhpeditor/renderer.php
@@ -28,19 +28,6 @@ function display_xml_error($error, $xml)
}
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>&nbsp;';
- }
- 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>&nbsp;';
- }
- echo '</div></div></div><div id="renderedpage">';
- echo "</div>";
}elseif (isset($_POST["check_xhp"])) {
libxml_use_internal_errors(true);
libxml_clear_errors();
@@ -100,12 +87,6 @@ if (isset($_POST["render_page"])) {
}
}
}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/views/menu.php b/help3/xhpeditor/views/menu.php
index 8725dd19..36e9da15 100644
--- a/help3/xhpeditor/views/menu.php
+++ b/help3/xhpeditor/views/menu.php
@@ -118,9 +118,9 @@
<div class="dropdown">
<button class="dropbtn">Tools</button>
<div class="dropdown-content">
- <input id="render_page" type="submit" form="CMtextarea" name="render_page" value="Render page"/>
- <input type="submit" form="CMtextarea" name="get_patch" value="Generate patch"/>
- <input id="check_xhp" type="submit" form="CMtextarea" name="check_xhp" value="Check XHP"/>
+ <a href="#" id="render_page" onclick="renderXHP()">Render Page</a>
+ <a href="#" id="check_xhp" onclick="checkXHP()" name="check_xhp">Check XHP</a>
+ <input type="submit" form="CMtextarea" name="get_patch" value="Generate patch" />
<input type="submit" form="CMtextarea" name="open_master" value="Open Master"/>
</div>
</div>