summaryrefslogtreecommitdiffstats
path: root/helpcontent2/help3xsl
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
commit940b4d1848e8c70ab7642901a68594e8016caffc (patch)
treeeb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /helpcontent2/help3xsl
parentInitial commit. (diff)
downloadlibreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz
libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'helpcontent2/help3xsl')
-rw-r--r--helpcontent2/help3xsl/README.prism.js.txt44
-rw-r--r--helpcontent2/help3xsl/README.txt71
-rw-r--r--helpcontent2/help3xsl/a11y-toggle.js100
-rw-r--r--helpcontent2/help3xsl/default.css907
-rw-r--r--helpcontent2/help3xsl/fuzzysort.js608
-rw-r--r--helpcontent2/help3xsl/generate_hid2file.xsl58
-rw-r--r--helpcontent2/help3xsl/get_bookmark.xsl193
-rw-r--r--helpcontent2/help3xsl/get_tree.xsl144
-rw-r--r--helpcontent2/help3xsl/help.html46
-rw-r--r--helpcontent2/help3xsl/help.js188
-rw-r--r--helpcontent2/help3xsl/help2.js263
-rw-r--r--helpcontent2/help3xsl/index.html19
-rw-r--r--helpcontent2/help3xsl/index2.html74
-rw-r--r--helpcontent2/help3xsl/normalize.css341
-rw-r--r--helpcontent2/help3xsl/online_transform.xsl1431
-rw-r--r--helpcontent2/help3xsl/paginathing.js243
-rw-r--r--helpcontent2/help3xsl/polyfills.js122
-rw-r--r--helpcontent2/help3xsl/prism.css270
-rw-r--r--helpcontent2/help3xsl/prism.js1519
-rw-r--r--helpcontent2/help3xsl/xap_templ_query.xsl295
20 files changed, 6936 insertions, 0 deletions
diff --git a/helpcontent2/help3xsl/README.prism.js.txt b/helpcontent2/help3xsl/README.prism.js.txt
new file mode 100644
index 000000000..fe0acc0d2
--- /dev/null
+++ b/helpcontent2/help3xsl/README.prism.js.txt
@@ -0,0 +1,44 @@
+Latest download version
+
+PrismJS 1.20.0
+
+Using prism.js for Basic code highlight
+
+http://prismjs.com
+
+License MIT (see prism.js)
+
+Download page http://prismjs.com/download
+
+Theme: Coy
+
+Languages to download: Visual Basic + Python + defaults pre-sets
+
+Plugins: line numbers,
+
+normalize-whitespace: configure after https://prismjs.com/plugins/normalize-whitespace/
+
+Prism.plugins.NormalizeWhitespace = new NormalizeWhitespace({
+'remove-trailing': true,
+'remove-indent': true,
+'left-trim': true,
+'right-trim': true,
+/*'break-lines': 80,
+'indent': 2,*/
+'remove-initial-line-feed': true,
+/*'tabs-to-spaces': 4,
+'spaces-to-tabs': 4*/
+});
+
+
+Usage:
+
+Add prism.js and prism.css to html page,
+
+Add class 'language-visual-basic' and 'line-numbers' to <code> as in
+
+<xsl:template match="bascode">
+ <div class="bascode" itemscope="true" itemtype="http://schema.org/SoftwareSourceCode" itemprop="codeSampleType" content="snippet">
+ <pre><code class="language-visual-basic line-numbers"><xsl:apply-templates /></code></pre></div>
+</xsl:template>
+
diff --git a/helpcontent2/help3xsl/README.txt b/helpcontent2/help3xsl/README.txt
new file mode 100644
index 000000000..0788c731a
--- /dev/null
+++ b/helpcontent2/help3xsl/README.txt
@@ -0,0 +1,71 @@
+Helpcontent displayed in a browser
+==================================
+
+This directory contains files needed to convert the XHP files to html, and
+also the html and css files needed for the actual rendering in the web
+browser.
+
+Building and translation of the XHP files is now integrated into the
+LibreOffice build process based on gbuild. If you want to use it, configure
+LibreOffice with one of the:
+
+ --with-help=html (for the local html files)
+ --with-help=online (for the html files that can be uploaded to a webserver)
+
+Using the online version
+------------------------
+
+When you have configured with --with-help=online, the result of the build is
+in
+
+ instdir/help
+
+You want to upload to your webserver like:
+
+ rsync -avz instdir/help/ username@webserver:/srv/www/htdocs/
+
+Then you also need to setup a link 'latest' on the server, like
+
+ ln -s 6.1 latest
+
+and make sure that symlinks are allowed in the webserver configuration.
+
+File descriptions
+-----------------
+
+* default.css:
+
+ the cascading style sheet for HTML formatting.
+
+* online_transform.xsl:
+
+ the XSL transform file. Transform XHP files into HTML files.
+
+ This file is a modification of xmlhelper/util/main_transform.xsl, which was designed for xmlhelp XSL processor.
+
+* help.js
+
+ This javascript file:
+
+ 1. modifies href attributes in <a> of #DisplayArea to handle &DbPAR and &System params
+ 2. picks the bookmarks file and displays in #BottomLeft <div> area.
+ 3. Reads URL params.
+
+New ‘Object’ tag
+----------------
+
+The filter online_transform.xsl now support the <object> tag defined for XHP files to allow a generic object in the browser. The <object> tag now maps to the following HTML5 tags:
+Maps to HTML5 <video> tag:
+
+<section id="video">
+ <object id="1232312" type ="video/ogg" data="movies/testvideo.ogv" height="480px" width="640px"/>
+</section>
+
+Maps to HTML5 <audio> tag:
+<section id="audio">
+ <object id="1232312" type ="audio/ogg" data="audio/testaudio.wav" height="" width=""/>
+</section>
+
+Maps to HTML5 <object> tag:
+
+ <object id="1232312" type ="{mimetype}" data="object/testobject.swf" height="" width=""/>
diff --git a/helpcontent2/help3xsl/a11y-toggle.js b/helpcontent2/help3xsl/a11y-toggle.js
new file mode 100644
index 000000000..821a8e027
--- /dev/null
+++ b/helpcontent2/help3xsl/a11y-toggle.js
@@ -0,0 +1,100 @@
+/*
+MIT License
+
+Copyright (c) 2016 Edenspiekermann
+
+*/
+
+(function () {
+ 'use strict';
+
+ var internalId = 0;
+ var togglesMap = {};
+ var targetsMap = {};
+
+ function $ (selector, context) {
+ return Array.prototype.slice.call(
+ (context || document).querySelectorAll(selector)
+ );
+ }
+
+ function getClosestToggle (element) {
+ if (element.closest) {
+ return element.closest('[data-a11y-toggle]');
+ }
+
+ while (element) {
+ if (element.nodeType === 1 && element.hasAttribute('data-a11y-toggle')) {
+ return element;
+ }
+
+ element = element.parentNode;
+ }
+
+ return null;
+ }
+
+ function handleToggle (toggle) {
+ var target = toggle && targetsMap[toggle.getAttribute('aria-controls')];
+
+ if (!target) {
+ return false;
+ }
+
+ var toggles = togglesMap['#' + target.id];
+ var isExpanded = target.getAttribute('aria-hidden') === 'false';
+
+ target.setAttribute('aria-hidden', isExpanded);
+ toggles.forEach(function (toggle) {
+ toggle.setAttribute('aria-expanded', !isExpanded);
+ });
+ }
+
+ var initA11yToggle = function (context) {
+ togglesMap = $('[data-a11y-toggle]', context).reduce(function (acc, toggle) {
+ var selector = '#' + toggle.getAttribute('data-a11y-toggle');
+ acc[selector] = acc[selector] || [];
+ acc[selector].push(toggle);
+ return acc;
+ }, togglesMap);
+
+ var targets = Object.keys(togglesMap);
+ targets.length && $(targets).forEach(function (target) {
+ var toggles = togglesMap['#' + target.id];
+ var isExpanded = target.hasAttribute('data-a11y-toggle-open');
+ var labelledby = [];
+
+ toggles.forEach(function (toggle) {
+ toggle.id || toggle.setAttribute('id', 'a11y-toggle-' + internalId++);
+ toggle.setAttribute('aria-controls', target.id);
+ toggle.setAttribute('aria-expanded', isExpanded);
+ labelledby.push(toggle.id);
+ });
+
+ target.setAttribute('aria-hidden', !isExpanded);
+ target.hasAttribute('aria-labelledby') || target.setAttribute('aria-labelledby', labelledby.join(' '));
+
+ targetsMap[target.id] = target;
+ });
+ };
+
+ document.addEventListener('DOMContentLoaded', function () {
+ initA11yToggle();
+ });
+
+ document.addEventListener('click', function (event) {
+ var toggle = getClosestToggle(event.target);
+ handleToggle(toggle);
+ });
+
+ document.addEventListener('keyup', function (event) {
+ if (event.which === 13 || event.which === 32) {
+ var toggle = getClosestToggle(event.target);
+ if (toggle && toggle.getAttribute('role') === 'button') {
+ handleToggle(toggle);
+ }
+ }
+ });
+
+ window && (window.a11yToggle = initA11yToggle);
+})();
diff --git a/helpcontent2/help3xsl/default.css b/helpcontent2/help3xsl/default.css
new file mode 100644
index 000000000..1d0beb269
--- /dev/null
+++ b/helpcontent2/help3xsl/default.css
@@ -0,0 +1,907 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+/*
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++ LIBREOFFICE HELP IN BROWSER +
++ DEFAULT STYLESHEET +
++ WESTERN LANGUAGES +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+We use px as the unit for navigation elements and fonts because we do
+not want them to scale with browser-set font size.
+We use rem as the unit for article and footer contents because they
+do not break anything related to layout by scaling.
+
+*/
+
+body,
+p,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+.listitem,
+.listitemintable,
+.tablecontent {
+ font-family: -apple-system, system-ui, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", "DejaVu Sans", "Lucida Grande", "Helvetica Neue", Helvetica, Arial, sans-serif, FreeSerif, NanumGothic, "Noto Sans Tibetan", Taprom;
+}
+.input {
+ background-color: rgba(0,0,0,0.04);
+ transition-property: background-color;
+ transition-duration: 150ms;
+ border-bottom: 1px dashed rgba(0,0,0,0.1);
+ font-family: Menlo, Consolas, "DejaVu Sans Mono", "Nimbus Mono L", "Lucida Sans Typewriter", "Courier New", Courier, Monaco, monospace;
+}
+[data-tooltip]{
+ position:relative;
+}
+[data-tooltip]::before {
+ content: "";
+ position: absolute;
+ top:-6px;
+ left:50%;
+ transform: translateX(-50%);
+ border-width: 4px 6px 0 6px;
+ border-style: solid;
+ border-color: rgba(0,0,0,0.7) transparent transparent transparent;
+ z-index: 100;
+ opacity: 0;
+ pointer-events: none;
+}
+[data-tooltip]::after {
+ content: attr(data-tooltip);
+ position: absolute;
+ left:50%;
+ top:-6px;
+ transform: translateX(-50%) translateY(-100%);
+ background: rgba(0,0,0,0.7);
+ text-align: center;
+ color: #fff;
+ padding:4px 2px;
+ font-size: 12px;
+ min-width: 80px;
+ border-radius: 5px;
+ opacity: 0;
+ pointer-events: none;
+}
+[data-tooltip]:hover:before, [data-tooltip]:hover:after {
+ opacity: 1;
+ pointer-events: auto;
+}
+body {
+ background-color: #F7F8F7;
+ margin: 0;
+ line-height: normal;
+}
+::selection {
+ background: #FFEB9F;
+}
+a {
+ text-decoration-color: rgba(0,0,0,0.15);
+ color: #0461e0;
+}
+a:hover {
+ text-decoration: underline;
+ color: #023a86;
+}
+a:visited {
+ color: #633363;
+}
+pre,
+.code,
+.codeintable,
+.example,
+.exampleintable,
+.literal,
+.literalintable,
+.path,
+.pathintable {
+ background-color: rgba(0,0,0,0.04);
+ border-radius: 2px;
+ display: inline;
+ padding: 1px 3px;
+ font-family: Menlo, Consolas, "DejaVu Sans Mono", "Nimbus Mono L", "Lucida Sans Typewriter", "Courier New", Courier, Monaco, monospace;
+}
+.smathcode {
+ border-radius: 2px;
+ padding: 1px 3px;
+ font-family: Menlo, Consolas, "DejaVu Sans Mono", "Nimbus Mono L", "Lucida Sans Typewriter", "Courier New", Courier, Monaco, monospace;
+}
+.acronym {
+ font-weight: bold;
+}
+.related {
+ font-weight: bold;
+ margin-top: 1.67rem;
+ border-top: 1px solid black;
+}
+.emph,
+.menuitem {
+ font-weight: bold;
+}
+.keycode {
+ font-family: Menlo, Consolas, "DejaVu Sans Mono", "Nimbus Mono L", "Lucida Sans Typewriter", "Courier New", Courier, Monaco, monospace;
+}
+.widget{
+ padding: 1px 10px;
+ background: #f0f0f0;
+ background: linear-gradient(to bottom,#f0f0f0,#fcfcfc);
+ border-radius: 3px;
+ color: #303030;
+ border: 1px solid #a0a0a0;
+ border-bottom-width: 2px;
+ white-space: nowrap;
+}
+/* div's for warning, tip and note */
+.note,
+.tip,
+.warning {
+ display:flex;
+ align-items: center;
+ border-radius: 0 4px 4px 0;
+ box-shadow: 0 2px 2px -2px rgba(0,0,0,0.2);
+ padding: 0.2em;
+ margin-top: 15px;
+}
+.note {
+ border-left: 3px solid #309048;
+ background-color: #d9f1dd;
+}
+.tip {
+ border-left: 3px solid #0063b1;
+ background-color: #cde5f7;
+}
+.warning {
+ border-left: 3px solid #ed8733;
+ background-color: #f6f1d2;
+}
+.noteicon, .notetext {
+ padding:0.3em;
+}
+
+/* Table related classes */
+
+/* Special case of table with one cell*/
+.onecell{
+ box-shadow: rgba(0,0,0,0.1) 0px 1px 3px 0px;
+ border-bottom: 1px solid #E8E8E8;
+}
+/* Special case of icon table*/
+.icontable {
+ display:flex;
+ align-items:center;
+}
+.iconcell {
+ padding:0.3em;
+}
+
+table {
+ background: #FEFEFE;
+ box-shadow: rgba(0,0,0,0.08) 0 1px 5px 0;
+ border-collapse: collapse;
+ margin-left: auto;
+ margin-right: auto;
+}
+table, th, td {
+ border-top: 0;
+ border-bottom: 1px solid #E8E8E8;
+ border-left: 0;
+ border-right: 0;
+ padding: 0.3em;
+}
+.tablehead,
+.tableheadintable {
+ font-weight: bold;
+ margin-top: 0px;
+}
+.tableheadcell {
+ color: white;
+ vertical-align:top;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ margin-bottom: 0.67rem;
+ color: #148603;
+}
+p,
+ol,
+td {
+ font-size: 1.17rem;
+ margin: 2px 0 2px 0;
+}
+h1 {
+ font-size: 1.83rem;
+ font-weight: 300;
+ border-bottom: 2px solid #148603;
+ margin-bottom: 1.67rem;
+}
+h1 a {
+ text-decoration: none;
+}
+h2 {
+ font-size: 1.55rem;
+}
+h3 {
+ font-size: 1.33rem;
+}
+h4,
+h5,
+h6 {
+ font-size: 1.17rem;
+}
+.relatedtopics {
+ font-weight: normal;
+}
+.howtoget {
+ background: #EBE7E9;
+ border-left: 3px solid #4E4B55;
+ border-radius: 0 4px 4px 0;
+ box-shadow: 0 2px 2px -2px rgba(0,0,0,0.2);
+ padding: 0.3em;
+ display: flex;
+ flex-direction: column;
+}
+.howtogetheader {
+ background: #FFF;
+ border-radius: 2px;
+ box-shadow: 0 2px 2px -2px rgba(0,0,0,0.2);
+ display: inline-block;
+ font-weight: bold;
+ padding: 0.1em 0.3em;
+}
+.howtogetbody {
+ padding: 0 0.3em;
+}
+.samplefilesection{
+}
+.wide {
+ width: 100%;
+}
+.bug {
+ color: red;
+}
+.debug {
+ border: 1px solid black;
+ padding: 3px;
+ display: none;
+ background-color: #222;
+ color: red;
+ text-align: left;
+}
+
+.pycode,
+.bascode {
+ border: solid 5px transparent;
+ margin-top: 15px;
+ margin-bottom: 15px;
+}
+
+#DisplayArea {
+ background-color: #FCFCFC;
+ overflow: auto;
+ padding: 10px 10px 40px 10px;
+ grid-area: main;
+}
+#DisplayArea > p {
+ margin-bottom: 10px;
+}
+.mediabutton {
+ background-color: cyan;
+}
+.mediadiv{
+ padding-bottom:5%;
+ height:0;
+ display:inline-block;
+ border:none;
+}
+.screenshot, .genericimage {
+ border: .5px solid rgba(0,0,0,.1);
+ border-radius: 3px;
+ margin-left: auto;
+ margin-right: auto;
+ margin-top: 2em;
+ margin-bottom: 2em;
+ display:block;
+ box-shadow: rgba(0,0,0,0.08) 0 1px 5px 0;
+}
+.iconimage {}
+
+.switch,
+.switchinline {}
+
+.embedded {}
+#TopLeftHeader {
+ grid-area: header;
+ position: sticky;
+ top: 0px;
+ color: #fff;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ z-index: 100;
+}
+.dropdowns {
+ /* allow for scrolling */
+ overflow-x: auto;
+ overflow-y: hidden;
+ /* make it smooth on iOS */
+ -webkit-overflow-scrolling: touch;
+ grid-area: dropdowns;
+ display: flex;
+ justify-content: space-between;
+ flex-direction: column;
+}
+.symbol, .logo, .logo:hover, .logo:visited {
+ color: #fff;
+ text-decoration: none;
+}
+.logo p {
+ font-size: 24px;
+}
+.symbol {
+ grid-area: symbol;
+ padding: 8px 8px 8px 20px;
+}
+.symbol div {
+ background-image: url(media/navigation/libo-symbol-white.svg);
+ background-repeat: no-repeat;
+ background-size: contain;
+ width: 52px;
+ height: 60px;
+}
+
+[data-a11y-toggle]:not([aria-controls]){
+ display: none;
+}
+
+#langs-nav:not([aria-hidden='true']), #modules-nav:not([aria-hidden='true']) {
+ z-index: 100;
+ /* line them up horizontally */
+ display: flex;
+ flex-direction: row;
+ /* allow for scrolling */
+ overflow-x: auto;
+ overflow-y: hidden;
+ /* make it smooth on iOS */
+ -webkit-overflow-scrolling: touch;
+}
+#langs-nav a, #modules-nav a {
+ color: #fff;
+ background-color: #233336;
+ display: block;
+ line-height: 1.5;
+ padding: 3px 6px;
+ text-decoration: none;
+ font-size: 24px;
+ flex-shrink: 0;
+ z-index: 100;
+ white-space: nowrap;
+}
+footer {
+ padding: 30px 20px;
+}
+footer p {
+ font-size: 0.98rem;
+}
+.contents-treeview input[type=checkbox], aside input[type=checkbox] {
+ /* from .visuallyhidden class of html5-boilerplate */
+ border: 0;
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
+ white-space: nowrap;
+}
+label[for=accordion-1] {
+ color: #233336;
+ display: block;
+ padding: 10px 0 10px 20px;
+ font-size: 22px;
+ line-height: .6;
+}
+label[for=accordion-1]:after {
+ font-size: 44px;
+ content:"⌄";
+}
+aside input[type=checkbox] ~ .contents-treeview {
+ display: none;
+}
+aside input[type=checkbox]:checked ~ .contents-treeview {
+ color: #333;
+ z-index: 6;
+ display: block;
+ margin: 0 20px 0 20px;
+}
+.index-label {
+ font-size: 22px;
+ color: #233336;
+ padding-left: 20px;
+ margin: 20px 0 0 0;
+}
+#Index, .index {
+ margin-top: 10px;
+}
+.index {
+ padding-left: 15px;
+}
+.index a {
+ font-size: 16px;
+ display: block;
+}
+.index .hidden {
+ display: none;
+}
+#Bookmarks {
+ padding: 0 20px;
+}
+#Bookmarks p {
+ font-size: 22px;
+ font-weight: bold;
+ color: #148603;
+}
+#WRITER::before {
+ content: "WRITER";
+ display: block;
+ font-size: 22px;
+ font-weight: bold;
+ color: #0369a3;
+}
+#CALC::before {
+ content: "CALC";
+ display: block;
+ font-size: 22px;
+ font-weight: bold;
+ color: #43c330;
+}
+#IMPRESS::before {
+ content: "IMPRESS";
+ display: block;
+ font-size: 22px;
+ font-weight: bold;
+ color: #a33e03;
+}
+#DRAW::before {
+ content: "DRAW";
+ display: block;
+ font-size: 22px;
+ font-weight: bold;
+ color: #c99c00;
+}
+#BASE::before {
+ content: "BASE";
+ display: block;
+ font-size: 22px;
+ font-weight: bold;
+ color: #8e03a3;
+}
+#MATH::before {
+ content: "MATH";
+ display: block;
+ font-size: 22px;
+ font-weight: bold;
+ color: darkslategray;
+}
+#CHART::before {
+ content: "CHART";
+ display: block;
+ font-size: 22px;
+ font-weight: bold;
+ color: darkcyan;
+}
+#BASIC::before {
+ content: "BASIC";
+ display: block;
+ font-size: 22px;
+ font-weight: bold;
+ color: black;
+}
+#SHARED::before {
+ content: "GLOBAL";
+ display: block;
+ font-size: 22px;
+ font-weight: bold;
+ color: gray;
+}
+.pagination-container {
+ text-align: center;
+ margin-left: -40px; /* The normalizer fails to account for this */
+}
+.pagination li {
+ display: inline-block;
+ padding: 0 5px;
+}
+.pagination a {
+ text-decoration: none;
+}
+li.active {
+ background-color: #023a86;
+}
+li.active a {
+ color: #fff;
+}
+li.disabled a {
+ opacity: 0.4;
+ pointer-events: none;
+}
+#search-bar, input {
+ border: 1px solid #CCC;
+ box-shadow: inset 0 1px 1px rgba(0,0,0,0.1);
+ box-sizing: border-box;
+ line-height: 1.5em;
+ margin-top: 10px;
+ outline: none;
+ padding: 0 .25em;
+ transition: all 0.30s ease-in-out;
+}
+#search-bar:focus, input:focus {
+ border: 1px solid #0EA5FB;
+}
+#search-bar {
+ width: 100%;
+}
+#search-bar::placeholder {
+ font-style: italic;
+}
+.xapian-donation {
+ border-top: 2px solid #148603;
+ background-color: #FCFCFC;
+ box-shadow: 0 2px 8px 0 rgba(0,0,0,.05);
+}
+#DonationFrame {
+ background: #18A303;
+ position: sticky;
+ top: 0px;
+}
+.donation{
+ background: linear-gradient(90deg, #4275b2 0%, #4eaa88 100%);
+ border-radius: 2px;
+ padding: 5px 10px;
+ margin: auto;
+ max-width: 200px;
+ color: #ffffff;
+}
+.donation:hover {
+ background: linear-gradient(90deg, #1c71d8 0%, #30c877 100%);
+}
+.donation a {
+ color: white;
+ text-decoration: none;
+}
+.donation p {
+ font-size:1.2rem;
+ text-align: center;
+}
+#SearchFrame {
+ background: #18A303;
+ top: 0px;
+ position: sticky;
+}
+.xapian-omega-search {
+ margin: auto;
+}
+.modules {
+ border-bottom: 2px solid #f3f3f3;
+ background-color: #233336;
+ z-index: 100;
+}
+#modules:after, #langs:after {
+ font-size: 30px;
+ color: #fff;
+ content:"⌄";
+}
+.lang {
+ background-color: #233336;
+}
+#langs, #modules {
+ display: none;
+}
+#modules-nav div {
+ background-repeat: no-repeat;
+ background-size: contain;
+ float: left;
+ display: none;
+}
+
+.calc-icon,
+.chart-icon,
+.writer-icon,
+.impress-icon,
+.draw-icon,
+.math-icon,
+.basic-icon,
+.base-icon {
+ width: 21.5px;
+ height: 26px;
+ position: relative;
+ margin-right: 5px;
+}
+.calc-icon {
+ background-image: url(media/navigation/libo-calc.svg);
+}
+.writer-icon {
+ background-image: url(media/navigation/libo-writer.svg);
+}
+.impress-icon {
+ background-image: url(media/navigation/libo-impress.svg);
+}
+.draw-icon {
+ background-image: url(media/navigation/libo-draw.svg);
+}
+.math-icon {
+ background-image: url(media/navigation/libo-math.svg);
+}
+.base-icon {
+ background-image: url(media/navigation/libo-base.svg);
+}
+.chart-icon {
+ background-image: url(media/navigation/libo-chart.svg);
+}
+.basic-icon {
+ background-image: url(media/navigation/libo-basic.svg);
+}
+/* tree view */
+
+.contents-treeview ul,
+.contents-treeview li {
+ padding: 0;
+ margin: 0;
+ list-style: none;
+ font-size: 16px;
+}
+.contents-treeview {
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ user-select: none;
+}
+.contents-treeview a, .index a {
+ text-decoration: none;
+ line-height: 1.4;
+}
+.contents-treeview a:hover, .index a:hover {
+ border-left: 2px solid rgba(0,0,0,0.05);
+ margin-left: -12px;
+ padding-left: 10px;
+}
+.contents-treeview input + label + ul {
+ margin: 0 0 0 22px;
+}
+.contents-treeview input ~ ul {
+ display: none;
+}
+.contents-treeview label,
+.contents-treeview label:before {
+ cursor: pointer;
+ color: #111;
+}
+.contents-treeview input:disabled + label {
+ cursor: default;
+ opacity: .6;
+}
+.contents-treeview input:checked:not(:disabled) ~ ul {
+ display: block;
+}
+.contents-treeview label,
+.contents-treeview a,
+.contents-treeview label::before {
+ display: block;
+ vertical-align: middle;
+}
+.contents-treeview label:before {
+ content: "⊞";
+ color: #0461e0;
+ width: 16px;
+ margin: 0 5px 0 0;
+ display: inline-block;
+}
+.contents-treeview input:checked + label::before {
+ content: "⊟";
+}
+.contents-current {
+ background: rgba(0,0,0,0.1);
+ border-left: 2px solid #6E7487;
+ margin-left: -12px;
+ padding-left: 10px;
+}
+/* webkit adjacent element selector bugfix */
+
+@media screen and (-webkit-min-device-pixel-ratio: 0) {
+ .contents-treeview {
+ -webkit-animation: webkit-adjacent-element-selector-bugfix infinite 1s;
+ }
+ @-webkit-keyframes webkit-adjacent-element-selector-bugfix {
+ from {
+ padding: 0;
+ }
+ to {
+ padding: 0;
+ }
+ }
+}
+@media screen and (min-width: 960px) {
+ .dropdowns {
+ flex-direction: row;
+ overflow-y: auto;
+ overflow-x: hidden;
+ }
+ #langs-nav, #modules-nav {
+ display: none;
+ }
+ #langs-nav a {
+ font-size: 19px;
+ white-space: normal;
+ }
+ /* these are buttons, so also reset some default stylings */
+ #langs, #modules {
+ cursor: pointer;
+ color: #fff;
+ font-size: 19px;
+ display: block;
+ background: transparent;
+ border: none;
+ text-transform: none;
+ padding: 0;
+ line-height: normal;
+ }
+
+ /* change the menu direction to stacked */
+ #langs-nav:not([aria-hidden='true']), #modules-nav:not([aria-hidden='true']) {
+ display: flex;
+ flex-direction: column;
+ overflow-y: auto;
+ overflow-x: hidden;
+ max-width: 120px;
+ max-height: 480px;
+ position: absolute;
+ }
+ #modules-nav {
+ background-color: #101820;
+ text-align: left;
+ }
+ #modules-nav div {
+ display: block;
+ }
+ #modules-nav a {
+ font-size: 19px;
+ }
+ aside {
+ float: left;
+ width: 320px;
+ }
+ .leftside {
+ grid-area: leftside;
+ }
+ .rightside {
+ grid-area: rightside;
+ }
+ #DonationFrame {
+ grid-area: donation;
+ }
+ #SearchFrame {
+ grid-area: search;
+ }
+ footer {
+ grid-area: footer;
+ }
+ .lang {
+ background-color: transparent;
+ }
+ .modules {
+ border: none;
+ background-color: transparent;
+ }
+ #DisplayArea {
+ box-shadow: 0 2px 8px 0 rgba(0,0,0,.05);
+ padding: 10px 50px 40px 50px;
+ }
+ .xapian-omega-search {
+ width: 100%;
+ }
+ .xapian-omega-search form {
+ display: flex;
+ justify-content: center;
+ }
+ .omega-autofocus {
+ max-width: 200px;
+ width: 100%
+ }
+}
+@media screen and (min-width: 1440px) {
+ #Contents {
+ color: #333;
+ z-index: 6;
+ display: block;
+ margin: 0 20px 0 20px;
+ }
+ label[for=accordion-1] {
+ background-color: transparent;
+ text-decoration: none;
+ }
+ label[for=accordion-1]:hover {
+ background-color: transparent;
+ }
+ label[for=accordion-1]:after {
+ content: "";
+ }
+ .omega-autofocus {
+ max-width: 400px;
+ }
+}
+/* Use @supports to sneak these rules past IE */
+@supports (grid-area: auto) {
+ @media screen and (min-width: 960px) {
+ #TopLeftHeader {
+ display: grid;
+ align-items: end;
+ grid-template-columns: auto auto;
+ grid-template-rows: auto auto;
+ grid-template-areas: "symbol logo"
+ "symbol dropdowns"
+ }
+ #SearchFrame {
+ grid-area: search;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+ #DonationFrame {
+ grid-area: donation;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+ body {
+ display: grid;
+ grid-template-columns: 320px 100px 300px 1fr;
+ grid-template-rows: minmax(1em, auto) minmax(1em, auto) 1fr minmax(1em, auto);
+ grid-template-areas: "header header search donation"
+ "rightside main main main"
+ "leftside main main main"
+ ". footer footer footer"
+ }
+ html {
+ scroll-padding-top: 64px;
+ }
+ }
+ @media screen and (min-width: 1440px) {
+ body {
+ display: grid;
+ grid-template-columns: 360px 100px 400px 400px 1fr;
+ grid-template-rows: 1fr minmax(1em, auto) minmax(1em, auto);
+ grid-template-areas: "header header search search donation"
+ "leftside main main main rightside"
+ ". footer footer footer ."
+ }
+ .donation {
+ max-width: 300px;
+ }
+ .rightside {
+ width: auto;
+ border-right: none;
+ }
+ }
+}
diff --git a/helpcontent2/help3xsl/fuzzysort.js b/helpcontent2/help3xsl/fuzzysort.js
new file mode 100644
index 000000000..71f173390
--- /dev/null
+++ b/helpcontent2/help3xsl/fuzzysort.js
@@ -0,0 +1,608 @@
+/*
+MIT License
+
+Copyright (c) 2018 Stephen Kamenar
+
+WHAT: SublimeText-like Fuzzy Search
+
+USAGE:
+ fuzzysort.single('fs', 'Fuzzy Search') // {score: -16}
+ fuzzysort.single('test', 'test') // {score: 0}
+ fuzzysort.single('doesnt exist', 'target') // null
+
+ fuzzysort.go('mr', ['Monitor.cpp', 'MeshRenderer.cpp'])
+ // [{score: -18, target: "MeshRenderer.cpp"}, {score: -6009, target: "Monitor.cpp"}]
+
+ fuzzysort.highlight(fuzzysort.single('fs', 'Fuzzy Search'), '<b>', '</b>')
+ // <b>F</b>uzzy <b>S</b>earch
+*/
+
+// UMD (Universal Module Definition) for fuzzysort
+;(function(root, UMD) {
+ if(typeof define === 'function' && define.amd) define([], UMD)
+ else if(typeof module === 'object' && module.exports) module.exports = UMD()
+ else root.fuzzysort = UMD()
+})(this, function UMD() { function fuzzysortNew(instanceOptions) {
+
+ var fuzzysort = {
+
+ single: function(search, target, options) {
+ if(!search) return null
+ if(!isObj(search)) search = fuzzysort.getPreparedSearch(search)
+
+ if(!target) return null
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ var allowTypo = options && options.allowTypo!==undefined ? options.allowTypo
+ : instanceOptions && instanceOptions.allowTypo!==undefined ? instanceOptions.allowTypo
+ : true
+ var algorithm = allowTypo ? fuzzysort.algorithm : fuzzysort.algorithmNoTypo
+ return algorithm(search, target, search[0])
+ // var threshold = options && options.threshold || instanceOptions && instanceOptions.threshold || -9007199254740991
+ // var result = algorithm(search, target, search[0])
+ // if(result === null) return null
+ // if(result.score < threshold) return null
+ // return result
+ },
+
+ go: function(search, targets, options) {
+ if(!search) return noResults
+ search = fuzzysort.prepareSearch(search)
+ var searchLowerCode = search[0]
+
+ var threshold = options && options.threshold || instanceOptions && instanceOptions.threshold || -9007199254740991
+ var limit = options && options.limit || instanceOptions && instanceOptions.limit || 9007199254740991
+ var allowTypo = options && options.allowTypo!==undefined ? options.allowTypo
+ : instanceOptions && instanceOptions.allowTypo!==undefined ? instanceOptions.allowTypo
+ : true
+ var algorithm = allowTypo ? fuzzysort.algorithm : fuzzysort.algorithmNoTypo
+ var resultsLen = 0; var limitedCount = 0
+ var targetsLen = targets.length
+
+ // This code is copy/pasted 3 times for performance reasons [options.keys, options.key, no keys]
+
+ // options.keys
+ if(options && options.keys) {
+ var scoreFn = options.scoreFn || defaultScoreFn
+ var keys = options.keys
+ var keysLen = keys.length
+ for(var i = targetsLen - 1; i >= 0; --i) { var obj = targets[i]
+ var objResults = new Array(keysLen)
+ for (var keyI = keysLen - 1; keyI >= 0; --keyI) {
+ var key = keys[keyI]
+ var target = getValue(obj, key)
+ if(!target) { objResults[keyI] = null; continue }
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ objResults[keyI] = algorithm(search, target, searchLowerCode)
+ }
+ objResults.obj = obj // before scoreFn so scoreFn can use it
+ var score = scoreFn(objResults)
+ if(score === null) continue
+ if(score < threshold) continue
+ objResults.score = score
+ if(resultsLen < limit) { q.add(objResults); ++resultsLen }
+ else {
+ ++limitedCount
+ if(score > q.peek().score) q.replaceTop(objResults)
+ }
+ }
+
+ // options.key
+ } else if(options && options.key) {
+ var key = options.key
+ for(var i = targetsLen - 1; i >= 0; --i) { var obj = targets[i]
+ var target = getValue(obj, key)
+ if(!target) continue
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ var result = algorithm(search, target, searchLowerCode)
+ if(result === null) continue
+ if(result.score < threshold) continue
+
+ // have to clone result so duplicate targets from different obj can each reference the correct obj
+ result = {target:result.target, _targetLowerCodes:null, _nextBeginningIndexes:null, score:result.score, indexes:result.indexes, obj:obj} // hidden
+
+ if(resultsLen < limit) { q.add(result); ++resultsLen }
+ else {
+ ++limitedCount
+ if(result.score > q.peek().score) q.replaceTop(result)
+ }
+ }
+
+ // no keys
+ } else {
+ for(var i = targetsLen - 1; i >= 0; --i) { var target = targets[i]
+ if(!target) continue
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ var result = algorithm(search, target, searchLowerCode)
+ if(result === null) continue
+ if(result.score < threshold) continue
+ if(resultsLen < limit) { q.add(result); ++resultsLen }
+ else {
+ ++limitedCount
+ if(result.score > q.peek().score) q.replaceTop(result)
+ }
+ }
+ }
+
+ if(resultsLen === 0) return noResults
+ var results = new Array(resultsLen)
+ for(var i = resultsLen - 1; i >= 0; --i) results[i] = q.poll()
+ results.total = resultsLen + limitedCount
+ return results
+ },
+
+ goAsync: function(search, targets, options) {
+ var canceled = false
+ var p = new Promise(function(resolve, reject) {
+ if(!search) return resolve(noResults)
+ search = fuzzysort.prepareSearch(search)
+ var searchLowerCode = search[0]
+
+ var q = fastpriorityqueue()
+ var iCurrent = targets.length - 1
+ var threshold = options && options.threshold || instanceOptions && instanceOptions.threshold || -9007199254740991
+ var limit = options && options.limit || instanceOptions && instanceOptions.limit || 9007199254740991
+ var allowTypo = options && options.allowTypo!==undefined ? options.allowTypo
+ : instanceOptions && instanceOptions.allowTypo!==undefined ? instanceOptions.allowTypo
+ : true
+ var algorithm = allowTypo ? fuzzysort.algorithm : fuzzysort.algorithmNoTypo
+ var resultsLen = 0; var limitedCount = 0
+ function step() {
+ if(canceled) return reject('canceled')
+
+ var startMs = Date.now()
+
+ // This code is copy/pasted 3 times for performance reasons [options.keys, options.key, no keys]
+
+ // options.keys
+ if(options && options.keys) {
+ var scoreFn = options.scoreFn || defaultScoreFn
+ var keys = options.keys
+ var keysLen = keys.length
+ for(; iCurrent >= 0; --iCurrent) { var obj = targets[iCurrent]
+ var objResults = new Array(keysLen)
+ for (var keyI = keysLen - 1; keyI >= 0; --keyI) {
+ var key = keys[keyI]
+ var target = getValue(obj, key)
+ if(!target) { objResults[keyI] = null; continue }
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ objResults[keyI] = algorithm(search, target, searchLowerCode)
+ }
+ objResults.obj = obj // before scoreFn so scoreFn can use it
+ var score = scoreFn(objResults)
+ if(score === null) continue
+ if(score < threshold) continue
+ objResults.score = score
+ if(resultsLen < limit) { q.add(objResults); ++resultsLen }
+ else {
+ ++limitedCount
+ if(score > q.peek().score) q.replaceTop(objResults)
+ }
+
+ if(iCurrent%1000/*itemsPerCheck*/ === 0) {
+ if(Date.now() - startMs >= 10/*asyncInterval*/) {
+ isNode?setImmediate(step):setTimeout(step)
+ return
+ }
+ }
+ }
+
+ // options.key
+ } else if(options && options.key) {
+ var key = options.key
+ for(; iCurrent >= 0; --iCurrent) { var obj = targets[iCurrent]
+ var target = getValue(obj, key)
+ if(!target) continue
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ var result = algorithm(search, target, searchLowerCode)
+ if(result === null) continue
+ if(result.score < threshold) continue
+
+ // have to clone result so duplicate targets from different obj can each reference the correct obj
+ result = {target:result.target, _targetLowerCodes:null, _nextBeginningIndexes:null, score:result.score, indexes:result.indexes, obj:obj} // hidden
+
+ if(resultsLen < limit) { q.add(result); ++resultsLen }
+ else {
+ ++limitedCount
+ if(result.score > q.peek().score) q.replaceTop(result)
+ }
+
+ if(iCurrent%1000/*itemsPerCheck*/ === 0) {
+ if(Date.now() - startMs >= 10/*asyncInterval*/) {
+ isNode?setImmediate(step):setTimeout(step)
+ return
+ }
+ }
+ }
+
+ // no keys
+ } else {
+ for(; iCurrent >= 0; --iCurrent) { var target = targets[iCurrent]
+ if(!target) continue
+ if(!isObj(target)) target = fuzzysort.getPrepared(target)
+
+ var result = algorithm(search, target, searchLowerCode)
+ if(result === null) continue
+ if(result.score < threshold) continue
+ if(resultsLen < limit) { q.add(result); ++resultsLen }
+ else {
+ ++limitedCount
+ if(result.score > q.peek().score) q.replaceTop(result)
+ }
+
+ if(iCurrent%1000/*itemsPerCheck*/ === 0) {
+ if(Date.now() - startMs >= 10/*asyncInterval*/) {
+ isNode?setImmediate(step):setTimeout(step)
+ return
+ }
+ }
+ }
+ }
+
+ if(resultsLen === 0) return resolve(noResults)
+ var results = new Array(resultsLen)
+ for(var i = resultsLen - 1; i >= 0; --i) results[i] = q.poll()
+ results.total = resultsLen + limitedCount
+ resolve(results)
+ }
+
+ isNode?setImmediate(step):step()
+ })
+ p.cancel = function() { canceled = true }
+ return p
+ },
+
+ highlight: function(result, hOpen, hClose) {
+ if(result === null) return null
+ if(hOpen === undefined) hOpen = '<b>'
+ if(hClose === undefined) hClose = '</b>'
+ var highlighted = ''
+ var matchesIndex = 0
+ var opened = false
+ var target = result.target
+ var targetLen = target.length
+ var matchesBest = result.indexes
+ for(var i = 0; i < targetLen; ++i) { var char = target[i]
+ if(matchesBest[matchesIndex] === i) {
+ ++matchesIndex
+ if(!opened) { opened = true
+ highlighted += hOpen
+ }
+
+ if(matchesIndex === matchesBest.length) {
+ highlighted += char + hClose + target.substr(i+1)
+ break
+ }
+ } else {
+ if(opened) { opened = false
+ highlighted += hClose
+ }
+ }
+ highlighted += char
+ }
+
+ return highlighted
+ },
+
+ prepare: function(target) {
+ if(!target) return
+ return {target:target, _targetLowerCodes:fuzzysort.prepareLowerCodes(target), _nextBeginningIndexes:null, score:null, indexes:null, obj:null} // hidden
+ },
+ prepareSlow: function(target) {
+ if(!target) return
+ return {target:target, _targetLowerCodes:fuzzysort.prepareLowerCodes(target), _nextBeginningIndexes:fuzzysort.prepareNextBeginningIndexes(target), score:null, indexes:null, obj:null} // hidden
+ },
+ prepareSearch: function(search) {
+ if(!search) return
+ return fuzzysort.prepareLowerCodes(search)
+ },
+
+
+
+ // Below this point is only internal code
+ // Below this point is only internal code
+ // Below this point is only internal code
+ // Below this point is only internal code
+
+
+
+ getPrepared: function(target) {
+ if(target.length > 999) return fuzzysort.prepare(target) // don't cache huge targets
+ var targetPrepared = preparedCache.get(target)
+ if(targetPrepared !== undefined) return targetPrepared
+ targetPrepared = fuzzysort.prepare(target)
+ preparedCache.set(target, targetPrepared)
+ return targetPrepared
+ },
+ getPreparedSearch: function(search) {
+ if(search.length > 999) return fuzzysort.prepareSearch(search) // don't cache huge searches
+ var searchPrepared = preparedSearchCache.get(search)
+ if(searchPrepared !== undefined) return searchPrepared
+ searchPrepared = fuzzysort.prepareSearch(search)
+ preparedSearchCache.set(search, searchPrepared)
+ return searchPrepared
+ },
+
+ algorithm: function(searchLowerCodes, prepared, searchLowerCode) {
+ var targetLowerCodes = prepared._targetLowerCodes
+ var searchLen = searchLowerCodes.length
+ var targetLen = targetLowerCodes.length
+ var searchI = 0 // where we at
+ var targetI = 0 // where you at
+ var typoSimpleI = 0
+ var matchesSimpleLen = 0
+
+ // very basic fuzzy match; to remove non-matching targets ASAP!
+ // walk through target. find sequential matches.
+ // if all chars aren't found then exit
+ for(;;) {
+ var isMatch = searchLowerCode === targetLowerCodes[targetI]
+ if(isMatch) {
+ matchesSimple[matchesSimpleLen++] = targetI
+ ++searchI; if(searchI === searchLen) break
+ searchLowerCode = searchLowerCodes[typoSimpleI===0?searchI : (typoSimpleI===searchI?searchI+1 : (typoSimpleI===searchI-1?searchI-1 : searchI))]
+ }
+
+ ++targetI; if(targetI >= targetLen) { // Failed to find searchI
+ // Check for typo or exit
+ // we go as far as possible before trying to transpose
+ // then we transpose backwards until we reach the beginning
+ for(;;) {
+ if(searchI <= 1) return null // not allowed to transpose first char
+ if(typoSimpleI === 0) { // we haven't tried to transpose yet
+ --searchI
+ var searchLowerCodeNew = searchLowerCodes[searchI]
+ if(searchLowerCode === searchLowerCodeNew) continue // doesn't make sense to transpose a repeat char
+ typoSimpleI = searchI
+ } else {
+ if(typoSimpleI === 1) return null // reached the end of the line for transposing
+ --typoSimpleI
+ searchI = typoSimpleI
+ searchLowerCode = searchLowerCodes[searchI + 1]
+ var searchLowerCodeNew = searchLowerCodes[searchI]
+ if(searchLowerCode === searchLowerCodeNew) continue // doesn't make sense to transpose a repeat char
+ }
+ matchesSimpleLen = searchI
+ targetI = matchesSimple[matchesSimpleLen - 1] + 1
+ break
+ }
+ }
+ }
+
+ var searchI = 0
+ var typoStrictI = 0
+ var successStrict = false
+ var matchesStrictLen = 0
+
+ var nextBeginningIndexes = prepared._nextBeginningIndexes
+ if(nextBeginningIndexes === null) nextBeginningIndexes = prepared._nextBeginningIndexes = fuzzysort.prepareNextBeginningIndexes(prepared.target)
+ var firstPossibleI = targetI = matchesSimple[0]===0 ? 0 : nextBeginningIndexes[matchesSimple[0]-1]
+
+ // Our target string successfully matched all characters in sequence!
+ // Let's try a more advanced and strict test to improve the score
+ // only count it as a match if it's consecutive or a beginning character!
+ if(targetI !== targetLen) for(;;) {
+ if(targetI >= targetLen) {
+ // We failed to find a good spot for this search char, go back to the previous search char and force it forward
+ if(searchI <= 0) { // We failed to push chars forward for a better match
+ // transpose, starting from the beginning
+ ++typoStrictI; if(typoStrictI > searchLen-2) break
+ if(searchLowerCodes[typoStrictI] === searchLowerCodes[typoStrictI+1]) continue // doesn't make sense to transpose a repeat char
+ targetI = firstPossibleI
+ continue
+ }
+
+ --searchI
+ var lastMatch = matchesStrict[--matchesStrictLen]
+ targetI = nextBeginningIndexes[lastMatch]
+
+ } else {
+ var isMatch = searchLowerCodes[typoStrictI===0?searchI : (typoStrictI===searchI?searchI+1 : (typoStrictI===searchI-1?searchI-1 : searchI))] === targetLowerCodes[targetI]
+ if(isMatch) {
+ matchesStrict[matchesStrictLen++] = targetI
+ ++searchI; if(searchI === searchLen) { successStrict = true; break }
+ ++targetI
+ } else {
+ targetI = nextBeginningIndexes[targetI]
+ }
+ }
+ }
+
+ { // tally up the score & keep track of matches for highlighting later
+ if(successStrict) { var matchesBest = matchesStrict; var matchesBestLen = matchesStrictLen }
+ else { var matchesBest = matchesSimple; var matchesBestLen = matchesSimpleLen }
+ var score = 0
+ var lastTargetI = -1
+ for(var i = 0; i < searchLen; ++i) { var targetI = matchesBest[i]
+ // score only goes down if they're not consecutive
+ if(lastTargetI !== targetI - 1) score -= targetI
+ lastTargetI = targetI
+ }
+ if(!successStrict) {
+ score *= 1000
+ if(typoSimpleI !== 0) score += -20/*typoPenalty*/
+ } else {
+ if(typoStrictI !== 0) score += -20/*typoPenalty*/
+ }
+ score -= targetLen - searchLen
+ prepared.score = score
+ prepared.indexes = new Array(matchesBestLen); for(var i = matchesBestLen - 1; i >= 0; --i) prepared.indexes[i] = matchesBest[i]
+
+ return prepared
+ }
+ },
+
+ algorithmNoTypo: function(searchLowerCodes, prepared, searchLowerCode) {
+ var targetLowerCodes = prepared._targetLowerCodes
+ var searchLen = searchLowerCodes.length
+ var targetLen = targetLowerCodes.length
+ var searchI = 0 // where we at
+ var targetI = 0 // where you at
+ var matchesSimpleLen = 0
+
+ // very basic fuzzy match; to remove non-matching targets ASAP!
+ // walk through target. find sequential matches.
+ // if all chars aren't found then exit
+ for(;;) {
+ var isMatch = searchLowerCode === targetLowerCodes[targetI]
+ if(isMatch) {
+ matchesSimple[matchesSimpleLen++] = targetI
+ ++searchI; if(searchI === searchLen) break
+ searchLowerCode = searchLowerCodes[searchI]
+ }
+ ++targetI; if(targetI >= targetLen) return null // Failed to find searchI
+ }
+
+ var searchI = 0
+ var successStrict = false
+ var matchesStrictLen = 0
+
+ var nextBeginningIndexes = prepared._nextBeginningIndexes
+ if(nextBeginningIndexes === null) nextBeginningIndexes = prepared._nextBeginningIndexes = fuzzysort.prepareNextBeginningIndexes(prepared.target)
+ var firstPossibleI = targetI = matchesSimple[0]===0 ? 0 : nextBeginningIndexes[matchesSimple[0]-1]
+
+ // Our target string successfully matched all characters in sequence!
+ // Let's try a more advanced and strict test to improve the score
+ // only count it as a match if it's consecutive or a beginning character!
+ if(targetI !== targetLen) for(;;) {
+ if(targetI >= targetLen) {
+ // We failed to find a good spot for this search char, go back to the previous search char and force it forward
+ if(searchI <= 0) break // We failed to push chars forward for a better match
+
+ --searchI
+ var lastMatch = matchesStrict[--matchesStrictLen]
+ targetI = nextBeginningIndexes[lastMatch]
+
+ } else {
+ var isMatch = searchLowerCodes[searchI] === targetLowerCodes[targetI]
+ if(isMatch) {
+ matchesStrict[matchesStrictLen++] = targetI
+ ++searchI; if(searchI === searchLen) { successStrict = true; break }
+ ++targetI
+ } else {
+ targetI = nextBeginningIndexes[targetI]
+ }
+ }
+ }
+
+ { // tally up the score & keep track of matches for highlighting later
+ if(successStrict) { var matchesBest = matchesStrict; var matchesBestLen = matchesStrictLen }
+ else { var matchesBest = matchesSimple; var matchesBestLen = matchesSimpleLen }
+ var score = 0
+ var lastTargetI = -1
+ for(var i = 0; i < searchLen; ++i) { var targetI = matchesBest[i]
+ // score only goes down if they're not consecutive
+ if(lastTargetI !== targetI - 1) score -= targetI
+ lastTargetI = targetI
+ }
+ if(!successStrict) score *= 1000
+ score -= targetLen - searchLen
+ prepared.score = score
+ prepared.indexes = new Array(matchesBestLen); for(var i = matchesBestLen - 1; i >= 0; --i) prepared.indexes[i] = matchesBest[i]
+
+ return prepared
+ }
+ },
+
+ prepareLowerCodes: function(str) {
+ var strLen = str.length
+ var lowerCodes = [] // new Array(strLen) sparse array is too slow
+ var lower = str.toLowerCase()
+ for(var i = 0; i < strLen; ++i) lowerCodes[i] = lower.charCodeAt(i)
+ return lowerCodes
+ },
+ prepareBeginningIndexes: function(target) {
+ var targetLen = target.length
+ var beginningIndexes = []; var beginningIndexesLen = 0
+ var wasUpper = false
+ var wasAlphanum = false
+ for(var i = 0; i < targetLen; ++i) {
+ var targetCode = target.charCodeAt(i)
+ var isUpper = targetCode>=65&&targetCode<=90
+ var isAlphanum = isUpper || targetCode>=97&&targetCode<=122 || targetCode>=48&&targetCode<=57
+ var isBeginning = isUpper && !wasUpper || !wasAlphanum || !isAlphanum
+ wasUpper = isUpper
+ wasAlphanum = isAlphanum
+ if(isBeginning) beginningIndexes[beginningIndexesLen++] = i
+ }
+ return beginningIndexes
+ },
+ prepareNextBeginningIndexes: function(target) {
+ var targetLen = target.length
+ var beginningIndexes = fuzzysort.prepareBeginningIndexes(target)
+ var nextBeginningIndexes = [] // new Array(targetLen) sparse array is too slow
+ var lastIsBeginning = beginningIndexes[0]
+ var lastIsBeginningI = 0
+ for(var i = 0; i < targetLen; ++i) {
+ if(lastIsBeginning > i) {
+ nextBeginningIndexes[i] = lastIsBeginning
+ } else {
+ lastIsBeginning = beginningIndexes[++lastIsBeginningI]
+ nextBeginningIndexes[i] = lastIsBeginning===undefined ? targetLen : lastIsBeginning
+ }
+ }
+ return nextBeginningIndexes
+ },
+
+ cleanup: cleanup,
+ new: fuzzysortNew,
+ }
+ return fuzzysort
+} // fuzzysortNew
+
+// This stuff is outside fuzzysortNew, because it's shared with instances of fuzzysort.new()
+var isNode = typeof require !== 'undefined' && typeof window === 'undefined'
+// var MAX_INT = Number.MAX_SAFE_INTEGER
+// var MIN_INT = Number.MIN_VALUE
+var preparedCache = new Map()
+var preparedSearchCache = new Map()
+var noResults = []; noResults.total = 0
+var matchesSimple = []; var matchesStrict = []
+function cleanup() { preparedCache.clear(); preparedSearchCache.clear(); matchesSimple = []; matchesStrict = [] }
+function defaultScoreFn(a) {
+ var max = -9007199254740991
+ for (var i = a.length - 1; i >= 0; --i) {
+ var result = a[i]; if(result === null) continue
+ var score = result.score
+ if(score > max) max = score
+ }
+ if(max === -9007199254740991) return null
+ return max
+}
+
+// prop = 'key' 2.5ms optimized for this case, seems to be about as fast as direct obj[prop]
+// prop = 'key1.key2' 10ms
+// prop = ['key1', 'key2'] 27ms
+function getValue(obj, prop) {
+ var tmp = obj[prop]; if(tmp !== undefined) return tmp
+ var segs = prop
+ if(!Array.isArray(prop)) segs = prop.split('.')
+ var len = segs.length
+ var i = -1
+ while (obj && (++i < len)) obj = obj[segs[i]]
+ return obj
+}
+
+function isObj(x) { return typeof x === 'object' } // faster as a function
+
+// Hacked version of https://github.com/lemire/FastPriorityQueue.js
+var fastpriorityqueue=function(){var r=[],o=0,e={};function n(){for(var e=0,n=r[e],c=1;c<o;){var f=c+1;e=c,f<o&&r[f].score<r[c].score&&(e=f),r[e-1>>1]=r[e],c=1+(e<<1)}for(var a=e-1>>1;e>0&&n.score<r[a].score;a=(e=a)-1>>1)r[e]=r[a];r[e]=n}return e.add=function(e){var n=o;r[o++]=e;for(var c=n-1>>1;n>0&&e.score<r[c].score;c=(n=c)-1>>1)r[n]=r[c];r[n]=e},e.poll=function(){if(0!==o){var e=r[0];return r[0]=r[--o],n(),e}},e.peek=function(e){if(0!==o)return r[0]},e.replaceTop=function(o){r[0]=o,n()},e};
+var q = fastpriorityqueue() // reuse this, except for async, it needs to make its own
+
+return fuzzysortNew()
+}) // UMD
+
+// TODO: (performance) wasm version!?
+
+// TODO: (performance) layout memory in an optimal way to go fast by avoiding cache misses
+
+// TODO: (performance) preparedCache is a memory leak
+
+// TODO: (like sublime) backslash === forwardslash
+
+// TODO: (performance) i have no idea how well optimized the allowing typos algorithm is
diff --git a/helpcontent2/help3xsl/generate_hid2file.xsl b/helpcontent2/help3xsl/generate_hid2file.xsl
new file mode 100644
index 000000000..59e2e4edd
--- /dev/null
+++ b/helpcontent2/help3xsl/generate_hid2file.xsl
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<!--
+Stylesheet to extract index bookmarks from xhp files and output a link to
+the xhp file.
+Usage:
+xsltproc get_bookmark.xsl <file.xhp>
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:output indent="yes" method="text"/>
+
+<!--
+############################
+# Variables and Parameters #
+############################
+//-->
+<xsl:variable name="fname" select="/helpdocument/meta/topic/filename"/>
+<xsl:variable name="filename">
+ <xsl:choose>
+ <xsl:when test="starts-with($fname, '/')">
+ <xsl:value-of select="substring($fname, 2)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$fname"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:variable>
+<!--
+#############
+# Templates #
+#############
+//-->
+
+<!-- Extract the bookmarks branches x filename-->
+<!--Special case for questions marks chars, that interferes in passing
+parameters in URLS-->
+<xsl:template match="/">
+ <xsl:variable name="href" select="concat(substring-before($filename,'xhp'),'html')"/>
+ <xsl:for-each select="//bookmark[@branch!='index']">
+ <xsl:variable name="aux" select="substring-after(@branch,'hid/')"/>
+ <xsl:text>'</xsl:text>
+ <xsl:choose>
+ <xsl:when test="not(contains($aux,'?'))"><xsl:value-of select="$aux"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="concat(substring-before($aux,'?'),'%3F',substring-after($aux,'?'))"/></xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>':'</xsl:text>
+ <xsl:value-of select="concat($href,'#',@id)"/><xsl:text>',&#xA;</xsl:text>
+ </xsl:for-each>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/helpcontent2/help3xsl/get_bookmark.xsl b/helpcontent2/help3xsl/get_bookmark.xsl
new file mode 100644
index 000000000..c53a55959
--- /dev/null
+++ b/helpcontent2/help3xsl/get_bookmark.xsl
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<!--
+Stylesheet to extract index bookmarks from xhp files and output a link to
+the xhp file.
+Usage:
+xsltproc get_bookmark.xsl <file.xhp>
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:param name="app"/>
+<xsl:param name="local"/>
+<xsl:param name="Language"/>
+<xsl:param name="productname"/>
+<xsl:param name="productversion"/>
+
+<xsl:output indent="yes" method="text"/>
+
+<!--
+############################
+# Variables and Parameters #
+############################
+//-->
+<xsl:variable name="fname" select="/helpdocument/meta/topic/filename"/>
+<xsl:variable name="filename">
+ <xsl:choose>
+ <xsl:when test="starts-with($fname, '/')">
+ <xsl:value-of select="substring($fname, 2)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$fname"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:variable>
+<!-- Product brand variables used in the help files -->
+<xsl:variable name="brand1" select="'$[officename]'"/>
+<xsl:variable name="brand2" select="'$[officeversion]'"/>
+<xsl:variable name="brand3" select="'%PRODUCTNAME'"/>
+<xsl:variable name="brand4" select="'%PRODUCTVERSION'"/>
+<!--
+#############
+# Templates #
+#############
+//-->
+
+<!-- Extract the bookmarks-->
+<xsl:template match="/">
+ <xsl:for-each select="//bookmark[@branch='index']">
+ <xsl:variable name="hrefhtml" select="substring-before($filename,'xhp')"/>
+ <xsl:variable name="href" select="concat($Language,'/',$hrefhtml,'html?DbPAR=',$app,'#',@id)"/>
+ <xsl:for-each select="bookmark_value">
+ <xsl:text disable-output-escaping="yes"><![CDATA[{url:"]]></xsl:text>
+ <xsl:value-of select="$href"/>
+ <xsl:text disable-output-escaping="yes"><![CDATA[", app:"]]></xsl:text>
+ <xsl:value-of select="$app"/>
+ <xsl:text disable-output-escaping="yes"><![CDATA[", text:"]]></xsl:text>
+ <xsl:call-template name="replace"><xsl:with-param name="text" select="."/></xsl:call-template>
+ <xsl:text disable-output-escaping="yes"><![CDATA["},]]>&#xA;</xsl:text>
+ </xsl:for-each>
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template name="replace">
+ <xsl:param name="text"/>
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string">
+ <xsl:call-template name="apostrophe">
+ <xsl:with-param name="string">
+ <xsl:call-template name="doublequote">
+ <xsl:with-param name="string">
+ <xsl:choose>
+ <xsl:when test="contains($text,';')">
+ <xsl:value-of select="substring-before($text,';')"/>
+ <xsl:text disable-output-escaping="yes"><![CDATA[ -- ]]></xsl:text>
+ <xsl:value-of select="substring-after($text,';')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$text"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+</xsl:template>
+
+<!-- weird characters inside bookmarks, replace by HTML entities-->
+<xsl:template name="apostrophe">
+ <xsl:param name="string"/>
+ <xsl:variable name="apost">&apos;</xsl:variable><!-- apostrophe -->
+ <xsl:choose>
+ <xsl:when test="contains($string,$apost)">
+ <xsl:variable name="newstr">
+ <xsl:value-of select="substring-before($string,$apost)"/>
+ <xsl:text disable-output-escaping="yes"><![CDATA[&]]>#39;</xsl:text>
+ <xsl:value-of select="substring-after($string,$apost)"/>
+ </xsl:variable>
+ <xsl:call-template name="apostrophe">
+ <xsl:with-param name="string" select="$newstr"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$string"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template name="doublequote">
+ <xsl:param name="string"/>
+ <xsl:variable name="dq">&quot;</xsl:variable><!-- double quote -->
+ <xsl:choose>
+ <xsl:when test="contains($string,$dq)">
+ <xsl:variable name="newstr">
+ <xsl:value-of select="substring-before($string,$dq)"/>
+ <xsl:text disable-output-escaping="yes"><![CDATA[&]]>#34;</xsl:text>
+ <xsl:value-of select="substring-after($string,$dq)"/>
+ </xsl:variable>
+ <xsl:call-template name="doublequote">
+ <xsl:with-param name="string" select="$newstr"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$string"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template name="brand" >
+ <xsl:param name="string"/>
+
+ <xsl:choose>
+
+ <xsl:when test="contains($string,$brand1)">
+ <xsl:variable name="newstr">
+ <xsl:value-of select="substring-before($string,$brand1)"/>
+ <xsl:value-of select="$productname"/>
+ <xsl:value-of select="substring-after($string,$brand1)"/>
+ </xsl:variable>
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string" select="$newstr"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="contains($string,$brand2)">
+ <xsl:variable name="newstr">
+ <xsl:value-of select="substring-before($string,$brand2)"/>
+ <xsl:value-of select="$pversion"/>
+ <xsl:value-of select="substring-after($string,$brand2)"/>
+ </xsl:variable>
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string" select="$newstr"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="contains($string,$brand3)">
+ <xsl:variable name="newstr">
+ <xsl:value-of select="substring-before($string,$brand3)"/>
+ <xsl:value-of select="$productname"/>
+ <xsl:value-of select="substring-after($string,$brand3)"/>
+ </xsl:variable>
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string" select="$newstr"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="contains($string,$brand4)">
+ <xsl:variable name="newstr">
+ <xsl:value-of select="substring-before($string,$brand4)"/>
+ <xsl:value-of select="$pversion"/>
+ <xsl:value-of select="substring-after($string,$brand4)"/>
+ </xsl:variable>
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string" select="$newstr"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:value-of select="$string"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/helpcontent2/help3xsl/get_tree.xsl b/helpcontent2/help3xsl/get_tree.xsl
new file mode 100644
index 000000000..df264d1b5
--- /dev/null
+++ b/helpcontent2/help3xsl/get_tree.xsl
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<!--
+Stylesheet to extract tree context and generate a nested list
+Usage:
+xsltproc get_tree.xsl <file.tree>
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:param name="lang"/>
+<xsl:param name="local"/>
+<xsl:param name="productversion"/>
+<xsl:param name="productname"/>
+<xsl:param name="module"/>
+<xsl:output indent="no" method="text"/>
+<!--
+############################
+# Variables and Parameters #
+############################
+//-->
+<!-- Product brand variables used in the help files -->
+<xsl:variable name="brand1" select="'$[officename]'"/>
+<xsl:variable name="brand2" select="'$[officeversion]'"/>
+<xsl:variable name="brand3" select="'%PRODUCTNAME'"/>
+<xsl:variable name="brand4" select="'%PRODUCTVERSION'"/>
+
+<!--
+#############
+# Templates #
+#############
+//-->
+<!-- Extract the tree and generate a nested UL-->
+<xsl:template match="/">
+ <xsl:apply-templates/>
+</xsl:template>
+<xsl:template match="help_section">
+ <![CDATA[<ul><li><input type="checkbox" id="]]><xsl:value-of select="@id"/><![CDATA["><label for="]]><xsl:value-of select="@id"/><![CDATA[">]]><xsl:call-template name="replace"><xsl:with-param name="text"><xsl:value-of select="@title"/></xsl:with-param></xsl:call-template><![CDATA[</label><ul>\]]><xsl:apply-templates/><![CDATA[</ul></li></ul>\]]>
+</xsl:template>
+
+<xsl:template match="node">
+ <![CDATA[<li><input type="checkbox" id="]]><xsl:value-of select="@id"/><![CDATA["><label for="]]><xsl:value-of select="@id"/><![CDATA[">]]><xsl:call-template name="replace"><xsl:with-param name="text"><xsl:value-of select="@title"/></xsl:with-param></xsl:call-template><![CDATA[</label><ul>\]]><xsl:apply-templates/><![CDATA[</ul></li>\]]>
+</xsl:template>
+
+<xsl:template match="topic">
+ <xsl:variable name="htmlpage">
+ <xsl:value-of select="concat($lang,'/',substring-before(substring-after(@id,'/'),'.xhp'),'.html','?DbPAR=',$module)" />
+ </xsl:variable>
+ <![CDATA[<li><a target="_top" href="]]><xsl:value-of select="$htmlpage"/><![CDATA[">]]><xsl:call-template name="replace"><xsl:with-param name="text"><xsl:value-of select="."/></xsl:with-param></xsl:call-template><![CDATA[</a></li>\]]>
+</xsl:template>
+
+<xsl:template name="replace">
+ <xsl:param name="text"/>
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string">
+ <xsl:call-template name="apostrophe">
+ <xsl:with-param name="string">
+ <xsl:value-of select="$text"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+</xsl:template>
+
+<!-- weird characters inside bookmarks, replace by HTML entities-->
+<xsl:template name="apostrophe">
+ <xsl:param name="string"/>
+ <xsl:variable name="apost">&apos;</xsl:variable><!-- apostrophe -->
+ <xsl:choose>
+ <xsl:when test="contains($string,$apost)">
+ <xsl:variable name="newstr">
+ <xsl:value-of select="substring-before($string,$apost)"/>
+ <xsl:text disable-output-escaping="yes"><![CDATA[&#39;]]></xsl:text>
+ <xsl:value-of select="substring-after($string,$apost)"/>
+ </xsl:variable>
+ <xsl:call-template name="apostrophe">
+ <xsl:with-param name="string" select="$newstr"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$string"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template name="brand" >
+ <xsl:param name="string"/>
+ <xsl:choose>
+
+ <xsl:when test="contains($string,$brand1)">
+ <xsl:variable name="newstr">
+ <xsl:value-of select="substring-before($string,$brand1)"/>
+ <xsl:value-of select="$productname"/>
+ <xsl:value-of select="substring-after($string,$brand1)"/>
+ </xsl:variable>
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string" select="$newstr"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="contains($string,$brand2)">
+ <xsl:variable name="newstr">
+ <xsl:value-of select="substring-before($string,$brand2)"/>
+ <xsl:value-of select="$pversion"/>
+ <xsl:value-of select="substring-after($string,$brand2)"/>
+ </xsl:variable>
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string" select="$newstr"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="contains($string,$brand3)">
+ <xsl:variable name="newstr">
+ <xsl:value-of select="substring-before($string,$brand3)"/>
+ <xsl:value-of select="$productname"/>
+ <xsl:value-of select="substring-after($string,$brand3)"/>
+ </xsl:variable>
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string" select="$newstr"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="contains($string,$brand4)">
+ <xsl:variable name="newstr">
+ <xsl:value-of select="substring-before($string,$brand4)"/>
+ <xsl:value-of select="$pversion"/>
+ <xsl:value-of select="substring-after($string,$brand4)"/>
+ </xsl:variable>
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string" select="$newstr"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:value-of select="$string"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/helpcontent2/help3xsl/help.html b/helpcontent2/help3xsl/help.html
new file mode 100644
index 000000000..df4885a67
--- /dev/null
+++ b/helpcontent2/help3xsl/help.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!--
+* This file is part of the LibreOffice project.
+*
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval' piwik.documentfoundation.org"/>
+</head>
+<body>
+<script type="text/javascript">
+ function getParameterByName(name, url) {
+ if (!url) {
+ url = window.location.href;
+ }
+ name = name.replace(/[\[\]]/g, "\\$&");
+ var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)");
+ var results = regex.exec(url);
+ if (!results) {
+ return null;
+ }
+ if (!results[2]) {
+ return '';
+ }
+ return decodeURIComponent(results[2].replace(/\+/g, " "));
+ }
+
+ var url = window.location.href;
+ var n = url.indexOf('?');
+ if (n != -1) {
+ // the URL came from LibreOffice help (F1)
+ var version = getParameterByName("Version", url);
+ var query = url.substr(n + 1, url.length);
+ var newURL = version + '/index.html?' + query;
+ window.location.href = newURL;
+ } else {
+ window.location.href = 'latest/index.html';
+ }
+</script>
+</body>
+</html>
+
diff --git a/helpcontent2/help3xsl/help.js b/helpcontent2/help3xsl/help.js
new file mode 100644
index 000000000..48fdca8bb
--- /dev/null
+++ b/helpcontent2/help3xsl/help.js
@@ -0,0 +1,188 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+// Pagination and fuzzy search
+var url = window.location.pathname;
+var moduleRegex = new RegExp('text\\/(\\w+)\\/');
+var regexArray = moduleRegex.exec(url);
+var modules = ['CALC', 'WRITER', 'IMPRESS', 'DRAW', 'BASE', 'MATH', 'CHART', 'BASIC', 'SHARED'];
+var indexEl = document.getElementsByClassName("index")[0];
+var fullLinks = fullLinkify(indexEl, bookmarks, modules, currentModule());
+var search = document.getElementById('search-bar');
+search.addEventListener('keyup', debounce(filter, 100, indexEl));
+// Preserve search input value during the session
+search.value = sessionStorage.getItem('searchsave');
+if (search.value !== undefined) {
+ filter(indexEl);
+}
+window.addEventListener('unload', function(event) {
+ sessionStorage.setItem('searchsave', search.value);
+});
+// render the unfiltered index list on page load
+fillIndex(indexEl, fullLinks, modules);
+
+function currentModule() {
+ var module = '';
+ // get the module name from the URL and remove the first character,
+ // but first deal with snowflake Base
+ if(url.indexOf('explorer/database/') !== -1) {
+ module = 'BASE';
+ } else {
+ if (null === regexArray){// comes from search or elsewhere, no defined module in URL
+ module = 'HARED'
+ } else {
+ module = regexArray[1].toUpperCase().substring(1);
+ }
+ }
+ return module;
+};
+function fullLinkify(indexEl, bookmarks, modules, currentModule) {
+ var fullLinkified = '';
+ // if user is not on a shared category page, limit the index to the current module + shared
+ if(currentModule !== 'HARED') {
+ bookmarks = bookmarks.filter(function(obj) {
+ return obj['app'] === currentModule || obj['app'] === 'SHARED';
+ });
+ }
+ bookmarks.forEach(function(obj) {
+ fullLinkified += '<a href="' + obj['url'] + '" class="' + obj['app'] + '">' + obj['text'] + '</a>';
+ });
+ return fullLinkified;
+}
+function fillIndex(indexEl, content, modules) {
+ indexEl.innerHTML = content;
+ var indexKids = indexEl.children;
+ for (var i = 0, len = indexKids.length; i < len; i++) {
+ indexKids[i].removeAttribute("id");
+ }
+ modules.forEach(function(module) {
+ var moduleHeader = indexEl.getElementsByClassName(module)[0];
+ if (typeof moduleHeader !== 'undefined') {
+ // let's wrap the header in a span, so the ::before element will not become a link
+ moduleHeader.outerHTML = '<span id="' + module + '" class="' + module + '">' + moduleHeader.outerHTML + '</span>';
+ }
+ });
+ Paginator(indexEl);
+}
+// filter the index list based on search field input
+function filter(indexList) {
+ var results = null;
+ var target = search.value.trim();
+ var filtered = '';
+ if (target.length < 1) {
+ fillIndex(indexEl, fullLinks, modules);
+ return;
+ }
+ results = fuzzysort.go(target, bookmarks, {threshold: -15000, key:'text'});
+
+ results.forEach(function(result) {
+ filtered += '<a href="' + result.obj['url'] + '" class="' + result.obj['app'] + '">' + fuzzysort.highlight(result) + '</a>';
+ });
+ fillIndex(indexList, filtered, modules);
+
+};
+// delay the rendering of the filtered results while user is typing
+function debounce(fn, wait, indexList) {
+ var timeout;
+ return function() {
+ clearTimeout(timeout);
+ timeout = setTimeout(function() {
+ fn.call(this, indexList);
+ }, (wait || 150));
+ };
+}
+
+// copy pycode and bascode to clipboard on mouse click
+// Show border when copy is done
+divcopyable(document.getElementsByClassName("bascode"));
+divcopyable(document.getElementsByClassName("pycode"));
+
+function divcopyable(itemcopyable){
+for (var i = 0, len = itemcopyable.length; i < len; i++) {
+ (function() {
+ var item = itemcopyable[i];
+
+ function changeBorder(item, color) {
+ var saveBorder = item.style.border;
+ item.style.borderColor = color;
+
+ setTimeout(function() {
+ item.style.border = saveBorder;
+ }, 150);
+ }
+ item.onclick = function() {
+ document.execCommand("copy");
+ changeBorder(item, "#18A303");
+ };
+ item.addEventListener("copy", function(event) {
+ event.preventDefault();
+ if (event.clipboardData) {
+ event.clipboardData.setData("text/plain", item.textContent);
+ }
+ });
+ }());
+}
+}
+
+// copy useful content to clipboard on mouse click
+var copyable = document.getElementsByClassName("input");
+for (var i = 0, len = copyable.length; i < len; i++) {
+ (function() {
+ var item = copyable[i];
+
+ function changeColor(item, color, colorToChangeBackTo) {
+ item.style.backgroundColor = color;
+ setTimeout(function() {
+ item.style.backgroundColor = colorToChangeBackTo;
+ }, 150);
+ }
+ item.onclick = function() {
+ document.execCommand("copy");
+ changeColor(item, "#18A303", "transparent");
+ };
+ item.addEventListener("copy", function(event) {
+ event.preventDefault();
+ if (event.clipboardData) {
+ event.clipboardData.setData("text/plain", item.textContent);
+ }
+ });
+ }());
+}
+// auto-expand contents per subitem
+var pathname = window.location.pathname;
+var pathRegex = /text\/.*\.html$/;
+var linkIndex = 0;
+var contentMatch = pathname.match(pathRegex);
+function linksMatch(content) {
+ var linkMatch = new RegExp(content);
+ var links = document.getElementById("Contents").getElementsByTagName("a");
+ for (var i = 0, len = links.length; i < len; i++) {
+ if (links[i].href.match(linkMatch)) {
+ return i;
+ }
+ }
+}
+linkIndex = linksMatch(contentMatch);
+if (typeof linkIndex !== "undefined") {
+ var current = document.getElementById("Contents").getElementsByTagName("a")[linkIndex];
+ var cItem = current.parentElement;
+ var parents = [];
+ while (cItem.parentElement && !cItem.parentElement.matches("#Contents") && parents.indexOf(cItem.parentElement) == -1) {
+ parents.push(cItem = cItem.parentElement);
+ }
+ var liParents = [].filter.call(parents, function(item) {
+ return item.matches("li");
+ });
+ for (var i = 0, len = liParents.length; i < len; i++) {
+ var input = liParents[i].querySelectorAll(':scope > input');
+ document.getElementById(input[0].id).checked = true;
+ }
+ current.classList.add('contents-current');
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/helpcontent2/help3xsl/help2.js b/helpcontent2/help3xsl/help2.js
new file mode 100644
index 000000000..95635c846
--- /dev/null
+++ b/helpcontent2/help3xsl/help2.js
@@ -0,0 +1,263 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+// Used to set Application in caseinline=APP
+function setApplSpan(spanZ) {
+ var module = getParameterByName("DbPAR");
+ if (module === null) {
+ module = "WRITER";
+ }
+ var y = spanZ.getElementsByTagName("SPAN");
+ var n = y.length;
+ var foundAppl = false;
+ for (i = 0; i < n; i++) {
+ if (y[i].getAttribute("id") === null){
+ continue;
+ }
+ else if( y[i].getAttribute("id").startsWith(module)){
+ y[i].removeAttribute("hidden");
+ foundAppl=true;
+ }
+ }
+ for (i = 0; i < n; i++) {
+ if (y[i].getAttribute("id") === null){
+ continue;
+ }
+ else if( y[i].getAttribute("id").startsWith("default")){
+ if(!foundAppl){
+ y[i].removeAttribute("hidden");
+ }
+ }
+ }
+}
+// Used to set system in case, caseinline=SYSTEM
+function setSystemSpan(spanZ) {
+ // if no System in URL, get browser system
+ var system = getParameterByName("System");
+ if (system === null) {
+ system = getSystem();
+ }
+ var y = spanZ.getElementsByTagName("SPAN");
+ var n = y.length;
+ var foundSystem = false;
+ for (i = 0; i < n; i++) {
+ if (y[i].getAttribute("id") === null){
+ continue;
+ }
+ else if( y[i].getAttribute("id").startsWith(system)){
+ y[i].removeAttribute("hidden");
+ foundSystem=true;
+ }
+ }
+ for (i = 0; i < n; i++) {
+ if (y[i].getAttribute("id") === null){
+ continue;
+ }
+ else if( y[i].getAttribute("id").startsWith("default")){
+ if(!foundSystem){
+ y[i].removeAttribute("hidden");
+ }
+ }
+ }
+}
+
+// paint headers and headings with appl color
+
+function moduleColor (module) {
+ switch (module){
+ case "WRITER" : {color="#0369A3"; break;}
+ case "CALC" : {color="#43C330"; break;}
+ case "CHART" : {color="darkcyan"; break;}
+ case "IMPRESS": {color="#A33E03"; break;}
+ case "DRAW" : {color="#C99C00"; break;}
+ case "BASE" : {color="#8E03A3"; break;}
+ case "BASIC" : {color="black"; break;}
+ case "MATH" : {color="darkslategray"; break;}
+ case "SHARED" : {color="gray"; break;}
+ default : {color="#18A303"; break;}
+ }
+ document.getElementById("TopLeftHeader").style.background = color;
+ document.getElementById("SearchFrame").style.background = color;
+ document.getElementById("DonationFrame").style.background = color;
+ var cols = document.getElementsByClassName('tableheadcell');
+ for(i = 0; i < cols.length; i++) {cols[i].style.backgroundColor = color;};
+ for (j of [1,2,3,4,5,6]) {
+ var hh = document.getElementsByTagName("H" + j);
+ for(i = 0; i < hh.length; i++) {
+ hh[i].style.color = color;
+ hh[i].style.borderBottomColor = color;
+ }
+ }
+}
+
+// Find spans that need the switch treatment and give it to them
+var spans = document.querySelectorAll("[class^=switch]");
+var n = spans.length;
+for (z = 0; z < n; z++) {
+ var id = spans[z].getAttribute("id");
+ if (id === null) {
+ continue;
+ }
+ else if (id.startsWith("swlnsys")) {
+ setSystemSpan(spans[z]);
+ } else {
+ setApplSpan(spans[z]);
+ }
+}
+/* add &DbPAR= and &System= to the links in DisplayArea div */
+/* skip for object files */
+function fixURL(module, system) {
+ if ((DisplayArea = document.getElementById("DisplayArea")) === null) return;
+ var itemlink = DisplayArea.getElementsByTagName("a");
+ var pSystem = (system === null) ? getSystem() : system;
+ var pAppl = (module === null) ? "WRITER" : module;
+ var n = itemlink.length;
+ for (var i = 0; i < n; i++) {
+ if (itemlink[i].getAttribute("class") != "objectfiles") {
+ setURLParam(itemlink[i], pSystem, pAppl);
+ }
+ }
+}
+//Set the params inside URL
+function setURLParam(itemlink, pSystem, pAppl) {
+ var href = itemlink.getAttribute("href");
+ if (href !== null) {
+ // skip external links
+ if (!href.startsWith("http")) {
+ // handle bookmark.
+ if (href.lastIndexOf('#') != -1) {
+ var postf = href.substring(href.lastIndexOf('#'), href.length);
+ var pref = href.substring(0, href.lastIndexOf('#'));
+ itemlink.setAttribute("href", pref + "?" + '&DbPAR=' + pAppl + '&System=' + pSystem + postf);
+ } else {
+ itemlink.setAttribute("href", href + "?" + '&DbPAR=' + pAppl + '&System=' + pSystem);
+ }
+ }
+ }
+}
+
+function getSystem() {
+ var system = "Unknown OS";
+ if (navigator.appVersion.indexOf("Win") != -1) system = "WIN";
+ if (navigator.appVersion.indexOf("Mac") != -1) system = "MAC";
+ if (navigator.appVersion.indexOf("X11") != -1) system = "UNIX";
+ if (navigator.appVersion.indexOf("Linux") != -1) system = "UNIX";
+ return system;
+}
+
+function getParameterByName(name, url) {
+ if (!url) {
+ url = window.location.href;
+ }
+ name = name.replace(/[\[\]]/g, "\\$&");
+ var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)");
+ var results = regex.exec(url);
+ if (!results) {
+ return null;
+ }
+ if (!results[2]) {
+ return '';
+ }
+ return decodeURIComponent(results[2].replace(/\+/g, " "));
+}
+
+function existingLang(lang) {
+ if (lang === undefined) {
+ return 'en-US';
+ }
+
+ if (languagesSet.has(lang)) {
+ return lang;
+ }
+
+ lang = lang.replace(/[-_].*/, '');
+ if (languagesSet.has(lang)) {
+ return lang;
+ }
+
+ return 'en-US';
+}
+
+function setupModules(lang) {
+ var modulesNav = document.getElementById('modules-nav');
+ if (!modulesNav.classList.contains('loaded')) {
+ var html =
+ '<a href="' + lang + '/text/swriter/main0000.html?DbPAR=WRITER"><div class="writer-icon"></div>Writer</a>' +
+ '<a href="' + lang + '/text/scalc/main0000.html?DbPAR=CALC"><div class="calc-icon"></div>Calc</a>' +
+ '<a href="' + lang + '/text/simpress/main0000.html?DbPAR=IMPRESS"><div class="impress-icon"></div>Impress</a>' +
+ '<a href="' + lang + '/text/sdraw/main0000.html?DbPAR=DRAW"><div class="draw-icon"></div>Draw</a>' +
+ '<a href="' + lang + '/text/sdatabase/main.html?DbPAR=BASE"><div class="base-icon"></div>Base</a>' +
+ '<a href="' + lang + '/text/smath/main0000.html?DbPAR=MATH"><div class="math-icon"></div>Math</a>' +
+ '<a href="' + lang + '/text/schart/main0000.html?DbPAR=CHART"><div class="chart-icon"></div>Chart</a>' +
+ '<a href="' + lang + '/text/sbasic/shared/main0601.html?DbPAR=BASIC"><div class="basic-icon"></div>Basic</a>';
+ modulesNav.innerHTML = html;
+ modulesNav.classList.add('loaded');
+ }
+}
+
+function setupLanguages(page) {
+ var langNav = document.getElementById('langs-nav');
+ if (!langNav.classList.contains('loaded')) {
+ var html = '';
+ languagesSet.forEach(function(lang) {
+ html += '<a href="' + lang + page + '">' + ((lang in languageNames)? languageNames[lang]: lang) + '</a>';
+ });
+ langNav.innerHTML = html;
+ langNav.classList.add('loaded');
+ }
+}
+
+// Test, if we are online
+if (document.body.getElementsByTagName('meta')) {
+ var _paq = _paq || [];
+ /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
+ _paq.push(['disableCookies']);
+ _paq.push(['trackPageView']);
+ _paq.push(['enableLinkTracking']);
+ (function() {
+ var u="//piwik.documentfoundation.org/";
+ _paq.push(['setTrackerUrl', u+'piwik.php']);
+ _paq.push(['setSiteId', '68']);
+ var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
+ g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
+ })();
+ var system = getParameterByName("System");
+} else {
+ var system = getSystem();
+}
+
+var module = getParameterByName("DbPAR");
+var helpID = getParameterByName("HID");
+fixURL(module,system);
+moduleColor(module);
+
+function debugInfo(dbg) {
+ if (dbg == null) return;
+ document.getElementById("DEBUG").style.display = "block";
+ document.getElementById("bm_module").innerHTML = "Module is: "+module;
+ document.getElementById("bm_system").innerHTML = "System is: "+system;
+ document.getElementById("bm_HID").innerHTML = "HID is: "+helpID;
+}
+
+debugInfo(getParameterByName("Debug"));
+
+// Mobile devices need the modules and langs on page load
+if (Math.max(document.documentElement.clientWidth, window.innerWidth || 0) < 960) {
+ var e = new Event('click');
+ var modulesBtn = document.getElementById('modules');
+ var langsBtn = document.getElementById('langs');
+ var modules = document.getElementById('modules-nav');
+ var langs = document.getElementById('langs-nav');
+ modules.setAttribute('data-a11y-toggle-open', '');
+ modulesBtn.dispatchEvent(e);
+ if (langs) {
+ langs.setAttribute('data-a11y-toggle-open', '');
+ langsBtn.dispatchEvent(e);
+ }
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/helpcontent2/help3xsl/index.html b/helpcontent2/help3xsl/index.html
new file mode 100644
index 000000000..69d7ee6af
--- /dev/null
+++ b/helpcontent2/help3xsl/index.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<!--
+* This file is part of the LibreOffice project.
+*
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval' piwik.documentfoundation.org"/>
+</head>
+<body>
+<script type="text/javascript">
+ window.location.href = 'latest/index.html';
+</script>
+</body>
+</html>
diff --git a/helpcontent2/help3xsl/index2.html b/helpcontent2/help3xsl/index2.html
new file mode 100644
index 000000000..b42007dd5
--- /dev/null
+++ b/helpcontent2/help3xsl/index2.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<!--
+* This file is part of the LibreOffice project.
+*
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval' piwik.documentfoundation.org"/>
+ <script type="text/javascript" src="polyfills.js"></script>
+ <script type="text/javascript" src="hid2file.js"></script>
+ <script type="text/javascript" src="languages.js"></script>
+ <script type="text/javascript" src="help2.js" defer></script>
+</head>
+<body>
+<script type="text/javascript">
+ // We have to wait until both the deferred help2.js and the document have loaded
+ window.addEventListener('DOMContentLoaded', function() {
+ var url = window.location.href;
+ var n = url.indexOf('index.html?');
+ if (n != -1) {
+ // the URL came from LibreOffice help (F1)
+ var target = getParameterByName("Target",url);
+ var lang = existingLang(getParameterByName("Language", url));
+ var system = getParameterByName("System", url);
+ var module;
+ var defaultFile;
+ var smodule = target.substr(0, target.indexOf('/'));
+ switch (smodule) {
+ case "swriter": {defaultFile='text/swriter/main0000.html';module="WRITER";break;}
+ case "scalc": {defaultFile='text/scalc/main0000.html';module="CALC";break;}
+ case "schart": {defaultFile='text/schart/main0000.html';module="CHART";break;}
+ case "simpress": {defaultFile='text/simpress/main0000.html';module="IMPRESS";break;}
+ case "sdraw": {defaultFile='text/sdraw/main0000.html';module="DRAW";break;}
+ case "smath": {defaultFile='text/smath/main0000.html';module="MATH";break;}
+ case "sdatabase": {defaultFile='text/sdatabase/main.html';module="BASE";break;}
+ case "sbasic": {defaultFile='text/sbasic/shared/main0601.html';module="BASIC";break;}
+ default: {defaultFile='text/shared/05/new_help.html';module="WRITER";break;}
+ }
+ //Special case of application F1 or menu Help -> LibreOffice Help
+ if (target.indexOf('.uno:HelpIndex') != -1) {
+ window.location.href = lang + '/' + defaultFile + '?System=' + system + '&DbPAR=' + module;
+ }
+ var bookmark = target.slice(target.indexOf('/') + 1, target.length);
+ var file = hid2fileMap[bookmark];
+ // check first if a root bookmark @@nowidget@@ can be used
+ if (file === undefined) {
+ var b2 = bookmark.substring(0, bookmark.lastIndexOf("/")) + '/@@nowidget@@';
+ file = hid2fileMap[b2];
+ }
+ // rebuild URL
+ if (file === undefined) {
+ var newURL = lang + '/' + defaultFile + '?System=' + system + '&DbPAR=' + module;
+ } else {
+ var indx = file.indexOf('#');
+ var bm = file.substr(indx,file.length);
+ file = file.substr(0,indx);
+ var newURL = lang + '/' + file + '?System=' + system + '&DbPAR=' + module + '&HID=' + bookmark + bm;
+ }
+ window.location.href = newURL;
+ } else {
+ // URL came from elsewhere, direct access to webroot, we redirect to main Help page
+ var system = 'WIN';
+ if (navigator.userAgent.indexOf("Mac") != -1) system = 'MAC';
+ if (navigator.userAgent.indexOf("Linux") != -1) system = 'UNIX';
+ window.location.href = existingLang(navigator.language) + '/text/shared/05/new_help.html?&DbPAR=WRITER&System=' + system;
+ }
+ });
+</script>
+</body>
+</html>
diff --git a/helpcontent2/help3xsl/normalize.css b/helpcontent2/help3xsl/normalize.css
new file mode 100644
index 000000000..47b010e47
--- /dev/null
+++ b/helpcontent2/help3xsl/normalize.css
@@ -0,0 +1,341 @@
+/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */
+
+/* Document
+ ========================================================================== */
+
+/**
+ * 1. Correct the line height in all browsers.
+ * 2. Prevent adjustments of font size after orientation changes in iOS.
+ */
+
+html {
+ line-height: 1.15; /* 1 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/* Sections
+ ========================================================================== */
+
+/**
+ * Remove the margin in all browsers.
+ */
+
+body {
+ margin: 0;
+}
+
+/**
+ * Correct the font size and margin on `h1` elements within `section` and
+ * `article` contexts in Chrome, Firefox, and Safari.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+/* Grouping content
+ ========================================================================== */
+
+/**
+ * 1. Add the correct box sizing in Firefox.
+ * 2. Show the overflow in Edge and IE.
+ */
+
+hr {
+ box-sizing: content-box; /* 1 */
+ height: 0; /* 1 */
+ overflow: visible; /* 2 */
+}
+
+/**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+pre {
+ font-family: monospace, monospace; /* 1 */
+ font-size: 1em; /* 2 */
+}
+
+/* Text-level semantics
+ ========================================================================== */
+
+/**
+ * Remove the gray background on active links in IE 10.
+ */
+
+a {
+ background-color: transparent;
+}
+
+/**
+ * 1. Remove the bottom border in Chrome 57-
+ * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
+ */
+
+abbr[title] {
+ border-bottom: none; /* 1 */
+ text-decoration: underline; /* 2 */
+ text-decoration: underline dotted; /* 2 */
+}
+
+/**
+ * Add the correct font weight in Chrome, Edge, and Safari.
+ */
+
+b,
+strong {
+ font-weight: bolder;
+}
+
+/**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+code,
+kbd,
+samp {
+ font-family: monospace, monospace; /* 1 */
+ font-size: 1em; /* 2 */
+}
+
+/**
+ * Add the correct font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` elements from affecting the line height in
+ * all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+sup {
+ top: -0.5em;
+}
+
+/* Embedded content
+ ========================================================================== */
+
+/**
+ * Remove the border on images inside links in IE 10.
+ */
+
+img {
+ border-style: none;
+}
+
+/* Forms
+ ========================================================================== */
+
+/**
+ * 1. Change the font styles in all browsers.
+ * 2. Remove the margin in Firefox and Safari.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ font-family: inherit; /* 1 */
+ font-size: 100%; /* 1 */
+ line-height: 1.15; /* 1 */
+ margin: 0; /* 2 */
+}
+
+/**
+ * Show the overflow in IE.
+ * 1. Show the overflow in Edge.
+ */
+
+button,
+input { /* 1 */
+ overflow: visible;
+}
+
+/**
+ * Remove the inheritance of text transform in Edge, Firefox, and IE.
+ * 1. Remove the inheritance of text transform in Firefox.
+ */
+
+button,
+select { /* 1 */
+ text-transform: none;
+}
+
+/**
+ * Correct the inability to style clickable types in iOS and Safari.
+ */
+
+button,
+[type="button"],
+[type="reset"],
+[type="submit"] {
+ -webkit-appearance: button;
+}
+
+/**
+ * Remove the inner border and padding in Firefox.
+ */
+
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+ border-style: none;
+ padding: 0;
+}
+
+/**
+ * Restore the focus styles unset by the previous rule.
+ */
+
+button:-moz-focusring,
+[type="button"]:-moz-focusring,
+[type="reset"]:-moz-focusring,
+[type="submit"]:-moz-focusring {
+ outline: 1px dotted ButtonText;
+}
+
+/**
+ * Correct the padding in Firefox.
+ */
+
+fieldset {
+ padding: 0.35em 0.75em 0.625em;
+}
+
+/**
+ * 1. Correct the text wrapping in Edge and IE.
+ * 2. Correct the color inheritance from `fieldset` elements in IE.
+ * 3. Remove the padding so developers are not caught out when they zero out
+ * `fieldset` elements in all browsers.
+ */
+
+legend {
+ box-sizing: border-box; /* 1 */
+ color: inherit; /* 2 */
+ display: table; /* 1 */
+ max-width: 100%; /* 1 */
+ padding: 0; /* 3 */
+ white-space: normal; /* 1 */
+}
+
+/**
+ * Add the correct vertical alignment in Chrome, Firefox, and Opera.
+ */
+
+progress {
+ vertical-align: baseline;
+}
+
+/**
+ * Remove the default vertical scrollbar in IE 10+.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+/**
+ * 1. Add the correct box sizing in IE 10.
+ * 2. Remove the padding in IE 10.
+ */
+
+[type="checkbox"],
+[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Correct the cursor style of increment and decrement buttons in Chrome.
+ */
+
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/**
+ * 1. Correct the odd appearance in Chrome and Safari.
+ * 2. Correct the outline style in Safari.
+ */
+
+[type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ outline-offset: -2px; /* 2 */
+}
+
+/**
+ * Remove the inner padding in Chrome and Safari on macOS.
+ */
+
+[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/**
+ * 1. Correct the inability to style clickable types in iOS and Safari.
+ * 2. Change font properties to `inherit` in Safari.
+ */
+
+::-webkit-file-upload-button {
+ -webkit-appearance: button; /* 1 */
+ font: inherit; /* 2 */
+}
+
+/* Interactive
+ ========================================================================== */
+
+/*
+ * Add the correct display in Edge, IE 10+, and Firefox.
+ */
+
+details {
+ display: block;
+}
+
+/*
+ * Add the correct display in all browsers.
+ */
+
+summary {
+ display: list-item;
+}
+
+/* Misc
+ ========================================================================== */
+
+/**
+ * Add the correct display in IE 10+.
+ */
+
+template {
+ display: none;
+}
+
+/**
+ * Add the correct display in IE 10.
+ */
+
+[hidden] {
+ display: none;
+}
diff --git a/helpcontent2/help3xsl/online_transform.xsl b/helpcontent2/help3xsl/online_transform.xsl
new file mode 100644
index 000000000..3a934dcb2
--- /dev/null
+++ b/helpcontent2/help3xsl/online_transform.xsl
@@ -0,0 +1,1431 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:output indent="yes" method="html" doctype-system= "about:legacy-compat"/>
+
+<xsl:include href="links.txt.xsl"/>
+<!--
+############################
+# Variables and Parameters #
+############################
+//-->
+
+<xsl:param name="local" />
+<xsl:param name="root"/>
+<xsl:param name="Language"/>
+<xsl:param name="productname"/>
+<xsl:param name="productversion"/>
+<xsl:param name="xapian"/>
+
+<xsl:param name="System" select="'WIN'"/>
+<xsl:param name="imgtheme" select="''"/>
+<xsl:param name="Id" />
+
+<!-- General Usage -->
+<xsl:variable name="am" select="'&amp;'"/>
+<xsl:variable name="sl" select="'/'"/>
+<xsl:variable name="qt" select="'&quot;'"/>
+
+<!-- For calculating pixel sizes -->
+<xsl:variable name="dpi" select="'96'"/>
+<xsl:variable name="dpcm" select="'38'"/>
+<xsl:variable name="dpmm" select="'3.8'"/>
+
+<!-- Product brand variables used in the help files -->
+<xsl:variable name="brand1" select="'$[officename]'"/>
+<xsl:variable name="brand2" select="'$[officeversion]'"/>
+<xsl:variable name="brand3" select="'%PRODUCTNAME'"/>
+<xsl:variable name="brand4" select="'%PRODUCTVERSION'"/>
+
+<!-- Installation -->
+<xsl:variable name="online" select="$local!='yes'"/>
+
+<!-- meta data variables from the help file -->
+<xsl:variable name="filename" select="/helpdocument/meta/topic/filename"/>
+<xsl:variable name="title" select="/helpdocument/meta/topic/title"/>
+
+<!-- the other parameters given by the help caller -->
+
+<xsl:variable name="pversion">
+ <xsl:value-of select="translate($productversion,' ','')"/>
+</xsl:variable>
+<!-- this is were the images are -->
+
+<xsl:variable name="lang" select="$Language"/>
+<xsl:variable name="urlpre" select="$root"/>
+
+
+<!-- generic Icon alt text -->
+<xsl:variable name="alttext" select="concat($root,'text/shared/00/icon_alt.xhp')"/>
+
+ <!-- parts of help and image urls -->
+
+<xsl:variable name="img_url_prefix" select="concat('media',$imgtheme,'/')"/>
+
+<xsl:variable name="urlpost" select="concat('?Language=',$lang,$am,'System=',$System,$am,'UseDB=no')"/>
+
+<xsl:variable name="linkprefix" select="concat($lang,'/')"/>
+
+<!--<xsl:variable name="linkpostfix" select="$urlpost"/>-->
+<xsl:variable name="linkpostfix" select="''"/>
+
+<!-- images for notes, tips and warnings -->
+<xsl:variable name="iconsizestyle" select="'width:40px;height:40px;'"/>
+<xsl:variable name="note_img" select="concat($img_url_prefix,'icon-themes/res/helpimg/note.svg')"/>
+<xsl:variable name="tip_img" select="concat($img_url_prefix,'icon-themes/res/helpimg/tip.svg')"/>
+<xsl:variable name="warning_img" select="concat($img_url_prefix,'icon-themes/res/helpimg/warning.svg')"/>
+
+<!-- Strings for the help UI page -->
+<xsl:variable name="tmp_href_ui"><xsl:value-of select="concat($urlpre,'text/shared/help/browserhelp.xhp')"/></xsl:variable>
+<xsl:variable name="tmp_doc_ui" select="document($tmp_href_ui)"/>
+<xsl:variable name ="ui_contents"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='contents']"/></xsl:variable>
+<xsl:variable name ="ui_index"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='index']"/></xsl:variable>
+<xsl:variable name ="ui_pholderall"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='pholderall']"/></xsl:variable>
+<xsl:variable name ="ui_pholderchosen"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='pholderchosen']"/></xsl:variable>
+<xsl:variable name ="ui_module"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='module']"/></xsl:variable>
+<xsl:variable name ="ui_language"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='language']"/></xsl:variable>
+<xsl:variable name ="ui_donate"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='donate']"/></xsl:variable>
+<xsl:variable name ="ui_logo"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='LibreOfficeHelp']"/></xsl:variable>
+<xsl:variable name ="ui_selectmodule"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='selectmodule']"/></xsl:variable>
+<xsl:variable name ="ui_selectlang"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='selectlanguage']"/></xsl:variable>
+<xsl:variable name ="ui_search"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='searchhelpcontents']"/></xsl:variable>
+<xsl:variable name ="ui_copyclip"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='copyclip']"/></xsl:variable>
+<!--
+#############
+# Templates #
+#############
+//-->
+
+<!-- Create the document skeleton -->
+<xsl:template match="/">
+ <xsl:variable name="htmlpage"><xsl:value-of select="concat(substring-before($filename,'.xhp'),'.html')"/></xsl:variable>
+ <xsl:variable name="titleL10N">
+ <xsl:call-template name="brand"><xsl:with-param name="string"><xsl:value-of select="$title"/></xsl:with-param></xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="install">
+ <xsl:call-template name="tokenize">
+ <xsl:with-param name="str" select="$filename"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="logoprodversion">
+ <xsl:choose>
+ <xsl:when test="$productversion='latest'"><xsl:value-of select="''"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="$productversion"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+<html lang="{$lang}">
+ <head>
+ <base href="{$install}"/>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <xsl:if test="$online">
+ <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval' piwik.documentfoundation.org"/>
+ </xsl:if>
+ <title><xsl:value-of select="$titleL10N"/></title>
+ <link rel="shortcut icon" href="media/navigation/favicon.ico"/>
+ <link type="text/css" href="normalize.css" rel="Stylesheet"/>
+ <link type="text/css" href="default.css" rel="Stylesheet"/>
+ <link type="text/css" href="prism.css" rel="Stylesheet"/>
+ <script type="text/javascript" src="polyfills.js"></script>
+ <script type="text/javascript" src="languages.js"></script>
+ <script type="text/javascript" src="{$lang}/langnames.js"></script>
+ <script type="text/javascript" src="fuzzysort.js"></script>
+ <script type="text/javascript" src="prism.js"></script>
+ <script type="text/javascript" src="help2.js" defer=""></script>
+ <script type="text/javascript" src="a11y-toggle.js" defer=""></script>
+ <script type="text/javascript" src="paginathing.js" defer=""></script>
+ <script type="text/javascript" src="{$lang}/bookmarks.js" defer=""></script>
+ <script type="text/javascript" src="{$lang}/contents.js" defer=""></script>
+ <script type="text/javascript" src="help.js" defer=""></script>
+ <meta name="viewport" content="width=device-width,initial-scale=1"/>
+ </head>
+ <body itemscope="true" itemtype="http://schema.org/TechArticle">
+ <xsl:if test="$online">
+ <!-- help2.js checks, if meta elements exist in the body -->
+ <meta itemprop="version" content="{$productversion}"/>
+ <meta itemprop="inLanguage" content="{$lang}"/>
+ <meta itemprop="datePublished" content="2017"/>
+ <meta itemprop="headline" content="{$titleL10N}"/>
+ </xsl:if>
+ <header id="TopLeftHeader">
+ <a class="symbol" href="{$lang}/text/shared/05/new_help.html">
+ <div></div>
+ </a>
+ <a class="logo" href="{$lang}/text/shared/05/new_help.html">
+ <p><xsl:value-of select="$ui_logo"/></p>
+ </a>
+ <div class="dropdowns">
+ <div class="modules">
+ <button type="button" data-a11y-toggle="modules-nav" id="modules" onclick="setupModules('{$lang}');">
+ <xsl:value-of select="$ui_module"/>
+ </button>
+ <nav id="modules-nav"/><!-- is filled in via setupModules() on demand -->
+ </div>
+ <xsl:if test="$online">
+ <div class="lang">
+ <button type="button" data-a11y-toggle="langs-nav" id="langs" onclick="setupLanguages('{$htmlpage}');">
+ <xsl:value-of select="$ui_language"/>
+ </button>
+ <nav id="langs-nav"/><!-- is filled in via setupLanguages() on demand -->
+ </div>
+ </xsl:if>
+ </div>
+ </header>
+ <aside class="rightside">
+ <input id="accordion-1" name="accordion-menu" type="checkbox"/>
+ <label for="accordion-1"><xsl:value-of select="$ui_contents"/></label>
+ <div id="Contents" class="contents-treeview"></div>
+ </aside>
+ <aside class="leftside">
+ <div id="Index">
+ <div class="index-label"><xsl:value-of select="$ui_index"/> &#32;&#x1f50e;&#xfe0e;&#32;</div>
+ <div id="Bookmarks">
+ <xsl:variable name="pholder">
+ <xsl:choose>
+ <xsl:when test="not(contains($htmlpage, '/text/shared/explorer/database/')) and contains($htmlpage, '/text/shared/')">
+ <xsl:value-of select="$ui_pholderall"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$ui_pholderchosen"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <input id="search-bar" type="text" class="search" placeholder="{$pholder}"/>
+ <nav class="index"></nav>
+ </div>
+ </div>
+ </aside>
+ <div id="DisplayArea" itemprop="articleBody">
+ <xsl:apply-templates select="/helpdocument/body"/>
+ </div>
+ <div id="SearchFrame">
+ <xsl:if test="$online">
+ <xsl:if test="$xapian='yes'">
+ <div class="xapian-omega-search">
+ <form name="P" method="get" action="/{$productversion}/{$lang}/search" target="_top">
+ <input id="omega-autofocus" type="search" name="P"/>
+ <input type="submit" class="xapian-omega-search-button" value="&#x1f50d;"/>
+ </form>
+ </div>
+ </xsl:if>
+ </xsl:if>
+ </div>
+ <div id="DonationFrame">
+ <xsl:if test="$online">
+ <div class="donation">
+ <p><a href="https://www.libreoffice.org/donate/?pk_campaign=help" target ="_blank"><xsl:value-of select="$ui_donate"/></a></p>
+ </div>
+ </xsl:if>
+ </div>
+ <footer>
+ <xsl:if test="$online">
+ <p><a href="https://www.libreoffice.org/imprint" target="_blank">Impressum (Legal Info)</a> | <a href="https://www.libreoffice.org/privacy" target="_blank">Privacy Policy</a> | <a href="https://www.documentfoundation.org/statutes.pdf" target="_blank">Statutes (non-binding English translation)</a> - <a href="https://www.documentfoundation.org/satzung.pdf" target="_blank">Satzung (binding German version)</a> | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the <a href="https://www.libreoffice.org/download/license/" target="_blank">Mozilla Public License v2.0</a>. “LibreOffice” and “The Document Foundation” are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our <a href="https://wiki.documentfoundation.org/TradeMark_Policy" target="_blank">trademark policy</a>. LibreOffice was based on OpenOffice.org.</p>
+ </xsl:if>
+ <div id="DEBUG" class="debug">
+ <h3 class="bug">Help content debug info:</h3>
+ <p>This page is: <a href="https://opengrok.libreoffice.org/xref/help/source{$filename}" target="_blank"><xsl:value-of select="$filename"/></a></p>
+ <p>Title is: <xsl:value-of select="$title"/></p>
+ <p id="bm_module"></p>
+ <p id="bm_system"></p>
+ <p id="bm_HID"></p>
+ </div>
+ </footer>
+ </body>
+</html>
+</xsl:template>
+
+<!-- AHELP -->
+<xsl:template match="ahelp">
+ <xsl:if test="not(@visibility='hidden')"><span class="avis"><xsl:apply-templates /></span></xsl:if>
+</xsl:template>
+
+<!-- ALT -->
+<xsl:template match="alt"/>
+
+<!-- MATHML -->
+<xsl:template match="math">
+<div class="mathml"><xsl:apply-templates /></div>
+</xsl:template>
+
+<!-- BOOKMARK -->
+<xsl:template match="bookmark">
+ <a name="{@id}"></a>
+ <xsl:choose>
+ <xsl:when test="starts-with(@branch,'hid')" />
+ <xsl:otherwise><xsl:apply-templates /></xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+<xsl:template match="bookmark" mode="embedded" />
+
+<!-- BOOKMARK_VALUE -->
+<xsl:template match="bookmark_value">
+ <xsl:variable name="aux1">
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string" select="."/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:element name="meta">
+ <xsl:attribute name="itemprop">keywords</xsl:attribute>
+ <xsl:attribute name="content"><xsl:value-of select="translate($aux1,';',',')"/></xsl:attribute>
+ </xsl:element>
+</xsl:template>
+
+<!-- BR -->
+<xsl:template match="br"><br /></xsl:template>
+<xsl:template match="br" mode="embedded"><br /></xsl:template>
+
+<!-- CAPTION -->
+<xsl:template match="caption" />
+
+<!-- CASE -->
+<xsl:template match="case"><xsl:call-template name="insertcase" /></xsl:template>
+<xsl:template match="case" mode="embedded">
+ <xsl:call-template name="insertcase">
+ <xsl:with-param name="embedded" select="'yes'"/>
+ </xsl:call-template>
+</xsl:template>
+
+<!-- CASEINLINE -->
+<xsl:template match="caseinline"><xsl:call-template name="insertcase" /></xsl:template>
+<xsl:template match="caseinline" mode="embedded">
+ <xsl:call-template name="insertcase">
+ <xsl:with-param name="embedded" select="'yes'"/>
+ </xsl:call-template>
+</xsl:template>
+
+<!-- COMMENT -->
+<xsl:template match="comment" />
+<xsl:template match="comment" mode="embedded"/>
+
+<!-- CREATED -->
+<xsl:template match="created" />
+
+<!-- DEFAULT -->
+<xsl:template match="default"><xsl:call-template name="insertdefault" /></xsl:template>
+<xsl:template match="default" mode="embedded">
+ <xsl:call-template name="insertdefault">
+ <xsl:with-param name="embedded" select="'yes'"/>
+ </xsl:call-template>
+</xsl:template>
+
+<!-- DEFAULTINLINE -->
+<xsl:template match="defaultinline"><xsl:call-template name="insertdefault" /></xsl:template>
+<xsl:template match="defaultinline" mode="embedded">
+ <xsl:call-template name="insertdefault">
+ <xsl:with-param name="embedded" select="'yes'"/>
+ </xsl:call-template>
+</xsl:template>
+
+<!-- EMBED -->
+<xsl:template match="embed"><xsl:call-template name="resolveembed"/></xsl:template>
+<xsl:template match="embed" mode="embedded"><xsl:call-template name="resolveembed"/></xsl:template>
+
+<!-- EMBEDVAR -->
+<xsl:template match="embedvar"><xsl:call-template name="resolveembedvar"/></xsl:template>
+<xsl:template match="embedvar" mode="embedded"><xsl:call-template name="resolveembedvar"/></xsl:template>
+
+<!-- EMPH -->
+<xsl:template match="emph">
+ <span class="emph"><xsl:apply-templates /></span>
+</xsl:template>
+<xsl:template match="emph" mode="embedded">
+ <span class="emph"><xsl:apply-templates /></span>
+</xsl:template>
+
+<!-- SUB -->
+<xsl:template match="sub">
+ <sub><xsl:apply-templates /></sub>
+</xsl:template>
+<xsl:template match="sub" mode="embedded">
+ <sub><xsl:apply-templates /></sub>
+</xsl:template>
+
+<!-- SUP -->
+<xsl:template match="sup">
+ <sup><xsl:apply-templates /></sup>
+</xsl:template>
+<xsl:template match="sup" mode="embedded">
+ <sup><xsl:apply-templates /></sup>
+</xsl:template>
+
+<!-- FILENAME -->
+<xsl:template match="filename"/>
+
+<!-- HISTORY -->
+<xsl:template match="history" />
+
+<!-- IMAGE -->
+<xsl:template match="image"><xsl:call-template name="insertimage"/></xsl:template>
+<xsl:template match="image" mode="embedded"><xsl:call-template name="insertimage"/></xsl:template>
+
+<!-- ITEM -->
+<xsl:template match="item">
+ <span class="{@type}">
+<!-- Insert tooltip only to input classes and only if the content is longer than 3 characters -->
+ <xsl:if test="@type='input' and string-length(.)>3">
+ <xsl:attribute name="data-tooltip">
+ <xsl:value-of select="$ui_copyclip"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates />
+ </span>
+</xsl:template>
+<xsl:template match="item" mode="embedded">
+ <span class="{@type}">
+ <xsl:if test="@type='input' and string-length(.)>3">
+ <xsl:attribute name="data-tooltip">
+ <xsl:value-of select="$ui_copyclip"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates />
+ </span>
+</xsl:template>
+
+<!-- LINK -->
+<xsl:template match="link">
+ <xsl:choose> <!-- don't insert the heading link to itself -->
+ <xsl:when test="(concat('/',@href) = /helpdocument/meta/topic/filename) or (@href = /helpdocument/meta/topic/filename)">
+ <xsl:apply-templates />
+ </xsl:when>
+ <xsl:when test="contains(child::embedvar/@href,'/00/00000004.xhp#wie')"> <!-- special treatment of howtoget links -->
+ <xsl:call-template name="insert_howtoget">
+ <xsl:with-param name="linkhref" select="@href"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="createlink" />
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+<xsl:template match="link" mode="embedded">
+ <xsl:call-template name="createlink"/>
+</xsl:template>
+
+<!-- LIST -->
+<xsl:template match="list">
+ <xsl:choose>
+ <xsl:when test="@type='ordered'">
+ <ol>
+ <xsl:if test="@startwith">
+ <xsl:attribute name="start"><xsl:value-of select="@startwith"/></xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates />
+ </ol>
+ </xsl:when>
+ <xsl:otherwise>
+ <ul><xsl:apply-templates /></ul>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template match="list" mode="embedded">
+ <xsl:choose>
+ <xsl:when test="@type='ordered'">
+ <ol>
+ <xsl:if test="@startwith">
+ <xsl:attribute name="start"><xsl:value-of select="@startwith"/></xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates mode="embedded"/>
+ </ol>
+ </xsl:when>
+ <xsl:otherwise>
+ <ul><xsl:apply-templates mode="embedded"/></ul>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- LISTITEM -->
+<xsl:template match="listitem">
+ <li><xsl:apply-templates /></li>
+</xsl:template>
+
+<xsl:template match="listitem" mode="embedded">
+ <li><xsl:apply-templates mode="embedded"/></li>
+</xsl:template>
+
+<!-- META, SEE HEADER -->
+<xsl:template match="meta" />
+
+<!-- OBJECT -->
+<xsl:template match="object">
+ <xsl:if test="$online">
+ <xsl:call-template name="insertobject"/>
+ </xsl:if>
+</xsl:template>
+<xsl:template match="object" mode="embedded">
+ <xsl:if test="$online">
+ <xsl:call-template name="insertobject"/>
+ </xsl:if>
+</xsl:template>
+
+<!-- PARAGRAPH -->
+<xsl:template match="paragraph">
+ <xsl:choose>
+
+ <xsl:when test="@role='heading'">
+ <xsl:call-template name="insertheading">
+ <xsl:with-param name="level" select="@level"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="@role='note' or @role='tip' or @role='warning'">
+ <xsl:call-template name="insertnote">
+ <xsl:with-param name="type" select="@role" />
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="contains(descendant::embedvar/@href,'/00/00000004.xhp#wie')"> <!-- special treatment of howtoget links -->
+ <xsl:apply-templates />
+ </xsl:when>
+
+ <xsl:when test="@role='bascode' or @role='pycode'">
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string" select="."/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="@role='smathcode'">
+ <p id="{@id}" class="smathcode"><span class="input" data-tooltip="{$ui_copyclip}"><xsl:apply-templates /></span></p>
+ </xsl:when>
+
+ <xsl:when test="@role='logocode'">
+ <xsl:call-template name="insertlogocode" />
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:call-template name="insertpara" />
+ </xsl:otherwise>
+
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template match="paragraph" mode="embedded">
+ <xsl:choose>
+ <xsl:when test="@role='heading'"> <!-- increase the level of headings that are embedded -->
+ <xsl:variable name="newlevel">
+ <xsl:choose>
+ <xsl:when test="@level='1'"><xsl:value-of select="'2'"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="@level"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:call-template name="insertheading">
+ <xsl:with-param name="level" select="$newlevel"/>
+ <xsl:with-param name="embedded" select="'yes'"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="@role='note' or @role='tip' or @role='warning'">
+ <xsl:call-template name="insertnote">
+ <xsl:with-param name="type" select="@role" />
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="contains(descendant::embedvar/@href,'/00/00000004.xhp#wie')"> <!-- special treatment of howtoget links -->
+ <xsl:apply-templates />
+ </xsl:when>
+
+ <xsl:when test="@role='bascode' or @role='pycode'">
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string" select="."/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="@role='smathcode'">
+ <p id="{@id}" class="smathcode"><span class="input" data-tooltip="{$ui_copyclip}"><xsl:apply-templates /></span></p>
+ </xsl:when>
+
+ <xsl:when test="@role='logocode'">
+ <xsl:call-template name="insertlogocode" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="insertpara" />
+ </xsl:otherwise>
+
+ </xsl:choose>
+</xsl:template>
+
+<!-- SECTION -->
+<xsl:template match="section">
+ <a name="{@id}"></a>
+ <xsl:choose>
+ <xsl:when test="@id='relatedtopics'">
+ <div class="relatedtopics">
+ <!--<xsl:variable name="href"><xsl:value-of select="concat($urlpre,'text/shared/00/00000004.xhp',$urlpost)"/></xsl:variable>-->
+ <xsl:variable name="href"><xsl:value-of select="concat($urlpre,'text/shared/00/00000004.xhp')"/></xsl:variable>
+ <xsl:variable name="anchor"><xsl:value-of select="'related'"/></xsl:variable>
+ <xsl:variable name="doc" select="document($href)"/>
+ <p class="related" itemprop="mentions">
+ <xsl:apply-templates select="$doc//variable[@id=$anchor]"/>
+ </p>
+ <div class="relatedbody" itemprop="mentions">
+ <xsl:apply-templates />
+ </div>
+ </div>
+ </xsl:when>
+ <xsl:when test="@id='howtoget'">
+ <xsl:call-template name="insert_howtoget" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- SECTION -->
+<xsl:template match="section" mode="embedded">
+ <a name="{@id}"></a>
+ <xsl:apply-templates mode="embedded"/>
+</xsl:template>
+
+<!-- SORT -->
+<xsl:template match="sort" >
+ <xsl:variable name="order1">
+ <xsl:choose>
+ <xsl:when test="string-length(@order) = 0"><xsl:value-of select="'ascending'"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="concat(@order,'ending')"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:apply-templates><xsl:sort order="{$order1}" select="descendant::paragraph"/></xsl:apply-templates>
+</xsl:template>
+<xsl:template match="sort" mode="embedded">
+ <xsl:variable name="order1">
+ <xsl:choose>
+ <xsl:when test="string-length(@order) = 0"><xsl:value-of select="'ascending'"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="concat(@order,'ending')"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:apply-templates><xsl:sort order="{$order1}" select="descendant::paragraph"/></xsl:apply-templates>
+</xsl:template>
+
+<!-- SWITCH -->
+<xsl:template match="switch">
+ <xsl:choose>
+ <xsl:when test ="@select = 'sys'">
+ <xsl:variable name="idsw" select="concat('swlnsys',generate-id())"/>
+ <span id="{$idsw}" class="switch">
+ <xsl:apply-templates />
+ </span>
+ </xsl:when>
+ <xsl:when test ="@select = 'appl'">
+ <xsl:variable name="idsw" select="concat('swlnappl',generate-id())"/>
+ <span id="{$idsw}" class="switch">
+ <xsl:apply-templates />
+ </span>
+ </xsl:when>
+ <xsl:otherwise>
+ <p class="debug">Unsupported switch condition.</p>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+<xsl:template match="switch" mode="embedded">
+ <xsl:choose>
+ <xsl:when test ="@select = 'sys'">
+ <xsl:variable name="idsw" select="concat('swlnsys',generate-id())"/>
+ <span id="{$idsw}" class="switch">
+ <xsl:apply-templates mode="embedded"/>
+ </span>
+ </xsl:when>
+ <xsl:when test ="@select = 'appl'">
+ <xsl:variable name="idsw" select="concat('swlnappl',generate-id())"/>
+ <span id="{$idsw}" class="switch">
+ <xsl:apply-templates mode="embedded"/>
+ </span>
+ </xsl:when>
+ <xsl:otherwise>
+ <p class="debug">Unsupported switch condition.</p>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- SWITCHINLINE -->
+<xsl:template match="switchinline">
+ <xsl:choose>
+ <xsl:when test ="@select = 'sys'">
+ <xsl:variable name="idsw" select="concat('swlnsys',generate-id())"/>
+ <span id="{$idsw}" class="switchinline">
+ <xsl:apply-templates />
+ </span>
+ </xsl:when>
+ <xsl:when test ="@select = 'appl'">
+ <xsl:variable name="idsw" select="concat('swlnappl',generate-id())"/>
+ <span id="{$idsw}" class="switchinline">
+ <xsl:apply-templates />
+ </span>
+ </xsl:when>
+ <xsl:otherwise>
+ <p class="debug">Unsupported switch condition.</p>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+<xsl:template match="switchinline" mode="embedded">
+ <xsl:choose>
+ <xsl:when test ="@select = 'sys'">
+ <xsl:variable name="idsw" select="concat('swlnsys',generate-id())"/>
+ <span id="{$idsw}" class="switchinline">
+ <xsl:apply-templates mode="embedded"/>
+ </span>
+ </xsl:when>
+ <xsl:when test ="@select = 'appl'">
+ <xsl:variable name="idsw" select="concat('swlnappl',generate-id())"/>
+ <span id="{$idsw}" class="switchinline">
+ <xsl:apply-templates mode="embedded"/>
+ </span>
+ </xsl:when>
+ <xsl:otherwise>
+ <p class="debug">Unsupported switch condition.</p>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- TABLE -->
+<xsl:template match="table"><xsl:call-template name="inserttable"/></xsl:template>
+<xsl:template match="table" mode="embedded"><xsl:call-template name="inserttable"/></xsl:template>
+
+<!-- TABLECELL -->
+<xsl:template match="tablecell">
+ <xsl:choose>
+ <xsl:when test="paragraph[@role='tablehead']">
+ <td rowspan="{@rowspan}" colspan="{@colspan}" class='tableheadcell'><xsl:apply-templates /></td>
+ </xsl:when>
+ <xsl:otherwise>
+ <td rowspan="{@rowspan}" colspan="{@colspan}"><xsl:apply-templates /></td>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+<xsl:template match="tablecell" mode="onecell"><xsl:apply-templates/></xsl:template>
+<xsl:template match="tablecell" mode="icontable"><div class="iconcell"><xsl:apply-templates/></div></xsl:template>
+<xsl:template match="tablecell" mode="embedded">
+ <xsl:choose>
+ <xsl:when test="paragraph[@role='tablehead']">
+ <td rowspan="{@rowspan}" colspan="{@colspan}" class='tableheadcell'><xsl:apply-templates mode="embedded"/></td>
+ </xsl:when>
+ <xsl:otherwise>
+ <td rowspan="{@rowspan}" colspan="{@colspan}"><xsl:apply-templates mode="embedded"/></td>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- TABLEROW -->
+<xsl:template match="tablerow"><tr><xsl:apply-templates /></tr></xsl:template>
+<xsl:template match="tablerow" mode="onecell"><xsl:apply-templates mode="onecell"/></xsl:template>
+<xsl:template match="tablerow" mode="icontable"><div class="icontable"><xsl:apply-templates mode="icontable"/></div></xsl:template>
+<xsl:template match="tablerow" mode="embedded"><tr><xsl:apply-templates mode="embedded"/></tr></xsl:template>
+
+<!-- TITLE -->
+<xsl:template match="title"/>
+
+<!-- TOPIC -->
+<xsl:template match="topic"/>
+
+<!-- VARIABLE -->
+<xsl:template match="variable"><a name="{@id}"></a><xsl:apply-templates /></xsl:template>
+<xsl:template match="variable" mode="embedded"><a name="{@id}"></a><xsl:apply-templates mode="embedded"/></xsl:template>
+
+<xsl:template match="text()">
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string"><xsl:value-of select="."/></xsl:with-param>
+ </xsl:call-template>
+</xsl:template>
+
+<xsl:template match="text()" mode="embedded">
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string"><xsl:value-of select="."/></xsl:with-param>
+ </xsl:call-template>
+</xsl:template>
+
+<!-- XHP extensions (2018) -->
+<!-- H1-H6 -->
+<xsl:template match="h1 | h2 | h3 | h4 | h5 | h6">
+ <xsl:element name="{local-name()}">
+ <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute><xsl:apply-templates />
+ </xsl:element>
+</xsl:template>
+<xsl:template match="h1 | h2 | h3 | h4 | h5 | h6" mode="embedded">
+ <xsl:element name="{concat('h',substring-after(local-name(),'h') + 1)}">
+ <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute><xsl:apply-templates mode="embedded"/>
+ </xsl:element>
+</xsl:template>
+
+<!-- INPUT -->
+<xsl:template match="input">
+ <span class="input" data-tooltip="{$ui_copyclip}"><xsl:apply-templates /></span>
+</xsl:template>
+<xsl:template match="input" mode="embedded">
+ <span class="input" data-tooltip="{$ui_copyclip}"><xsl:apply-templates mode="embedded"/></span>
+</xsl:template>
+
+<!--MENUITEM, KEYCODE, LITERAL, WIDGET-->
+<xsl:template match="menuitem | keycode | literal | widget">
+ <span class="{local-name()}"><xsl:apply-templates /></span>
+</xsl:template>
+<xsl:template match="menuitem | input | keycode | literal" mode="embedded">
+ <span class="{local-name()}"><xsl:apply-templates mode="embedded"/></span>
+</xsl:template>
+
+<!--NOTE TIP AND WARNING-->
+<xsl:template match="tip | note | warning">
+ <xsl:variable name="imgsrc">
+ <xsl:choose>
+ <xsl:when test="local-name()='note'"><xsl:value-of select="$note_img"/></xsl:when>
+ <xsl:when test="local-name()='tip'"><xsl:value-of select="$tip_img"/></xsl:when>
+ <xsl:when test="local-name()='warning'"><xsl:value-of select="$warning_img"/></xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <div class="{local-name()}">
+ <div class="noteicon"><img src="{$imgsrc}" alt="{local-name()}" title="{local-name()}" style="{$iconsizestyle}"/></div>
+ <div class="notetext"><p id="{@id}"><xsl:apply-templates /></p></div>
+ </div>
+ <br/>
+</xsl:template>
+<xsl:template match="tip | note | warning" mode="embedded">
+ <xsl:variable name="imgsrc">
+ <xsl:choose>
+ <xsl:when test="local-name()='note'"><xsl:value-of select="$note_img"/></xsl:when>
+ <xsl:when test="local-name()='tip'"><xsl:value-of select="$tip_img"/></xsl:when>
+ <xsl:when test="local-name()='warning'"><xsl:value-of select="$warning_img"/></xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <div class="{local-name()}">
+ <div class="noteicon"><img src="{$imgsrc}" alt="{local-name()}" title="{local-name()}" style="{$iconsizestyle}"/></div>
+ <div class="notetext"><p id="{@id}"><xsl:apply-templates mode="embedded"/></p></div>
+ </div>
+ <br/>
+</xsl:template>
+
+<!-- In case of missing help files -->
+<xsl:template match="help-id-missing"><xsl:value-of select="$Id"/></xsl:template>
+
+<!--
+###################
+# NAMED TEMPLATES #
+###################
+//-->
+
+<!-- Branding -->
+<xsl:template name="brand" >
+ <xsl:param name="string"/>
+
+ <xsl:choose>
+
+ <xsl:when test="contains($string,$brand1)">
+ <xsl:variable name="newstr">
+ <xsl:value-of select="substring-before($string,$brand1)"/>
+ <xsl:value-of select="$productname"/>
+ <xsl:value-of select="substring-after($string,$brand1)"/>
+ </xsl:variable>
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string" select="$newstr"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="contains($string,$brand2)">
+ <xsl:variable name="newstr">
+ <xsl:value-of select="substring-before($string,$brand2)"/>
+ <xsl:value-of select="$pversion"/>
+ <xsl:value-of select="substring-after($string,$brand2)"/>
+ </xsl:variable>
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string" select="$newstr"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="contains($string,$brand3)">
+ <xsl:variable name="newstr">
+ <xsl:value-of select="substring-before($string,$brand3)"/>
+ <xsl:value-of select="$productname"/>
+ <xsl:value-of select="substring-after($string,$brand3)"/>
+ </xsl:variable>
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string" select="$newstr"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="contains($string,$brand4)">
+ <xsl:variable name="newstr">
+ <xsl:value-of select="substring-before($string,$brand4)"/>
+ <xsl:value-of select="$pversion"/>
+ <xsl:value-of select="substring-after($string,$brand4)"/>
+ </xsl:variable>
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string" select="$newstr"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:value-of select="$string"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+</xsl:template>
+
+<!-- Insert Paragraph -->
+<xsl:template name="insertpara">
+ <xsl:variable name="role">
+ <xsl:choose>
+ <xsl:when test="ancestor::table">
+ <xsl:value-of select="concat(@role,'intable')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@role"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <p id="{@id}" class="{$role}"><xsl:apply-templates /></p>
+</xsl:template>
+
+<xsl:template match="bascode">
+ <div class="bascode" itemscope="true" itemtype="http://schema.org/SoftwareSourceCode" itemprop="codeSampleType" content="snippet">
+ <xsl:attribute name="data-tooltip"><xsl:value-of select="$ui_copyclip"/></xsl:attribute>
+ <pre><code class="language-visual-basic line-numbers"><xsl:apply-templates /></code></pre>
+ </div>
+</xsl:template>
+<xsl:template match="bascode" mode="embedded">
+ <div class="bascode" itemscope="true" itemtype="http://schema.org/SoftwareSourceCode" itemprop="codeSampleType" content="snippet">
+ <xsl:attribute name="data-tooltip"><xsl:value-of select="$ui_copyclip"/></xsl:attribute>
+ <pre><code class="language-visual-basic line-numbers"><xsl:apply-templates mode="embedded" /></code></pre>
+ </div>
+</xsl:template>
+
+<xsl:template match="pycode">
+ <div class="pycode" itemscope="true" itemtype="http://schema.org/SoftwareSourceCode" itemprop="codeSampleType" content="snippet">
+ <xsl:attribute name="data-tooltip"><xsl:value-of select="$ui_copyclip"/></xsl:attribute>
+ <pre><code class="language-python line-numbers"><xsl:apply-templates /></code></pre>
+ </div>
+</xsl:template>
+<xsl:template match="pycode" mode="embedded">
+ <div class="pycode" itemscope="true" itemtype="http://schema.org/SoftwareSourceCode" itemprop="codeSampleType" content="snippet">
+ <xsl:attribute name="data-tooltip"><xsl:value-of select="$ui_copyclip"/></xsl:attribute>
+ <pre><code class="language-python line-numbers"><xsl:apply-templates mode="embedded" /></code></pre>
+ </div>
+</xsl:template>
+
+<!-- Insert Logo code snippet -->
+<xsl:template name="insertlogocode">
+ <pre><xsl:apply-templates /></pre>
+</xsl:template>
+
+<!-- Insert "How to get Link" -->
+<xsl:template name="insert_howtoget">
+ <xsl:param name="linkhref" />
+ <xsl:variable name="archive" select="'shared'"/>
+ <xsl:variable name="tmp_href"><xsl:value-of select="concat($urlpre,'text/shared/00/00000004.xhp')"/></xsl:variable>
+ <xsl:variable name="tmp_doc" select="document($tmp_href)"/>
+ <div class="howtoget">
+ <div>
+ <p class="howtogetheader"><xsl:apply-templates select="$tmp_doc//variable[@id='wie']"/></p>
+ </div>
+ <div class="howtogetbody">
+ <xsl:choose>
+ <xsl:when test="$linkhref = ''"> <!-- new style -->
+ <xsl:apply-templates/>
+ </xsl:when>
+ <xsl:otherwise> <!-- old style -->
+ <xsl:variable name="href"><xsl:value-of select="concat($urlpre,substring-before($linkhref,'#'))"/></xsl:variable>
+ <xsl:variable name="anc"><xsl:value-of select="substring-after($linkhref,'#')"/></xsl:variable>
+ <xsl:variable name="docum" select="document($href)"/>
+ <xsl:call-template name="insertembed">
+ <xsl:with-param name="doc" select="$docum" />
+ <xsl:with-param name="anchor" select="$anc" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </div>
+ </div>
+ <br/>
+</xsl:template>
+
+<!-- Create a link -->
+<xsl:template name="createlink">
+ <xsl:choose>
+ <xsl:when test="starts-with(@href,'http://') or starts-with(@href,'https://')"> <!-- web links -->
+ <a target ="_blank" href="{@href}"><xsl:apply-templates /></a>
+ </xsl:when>
+ <xsl:when test="contains(@href,'#')"> <!-- internal links with bookmark -->
+ <xsl:variable name="anchor"><xsl:value-of select="concat('#',substring-after(@href,'#'))"/></xsl:variable>
+ <xsl:variable name="href"><xsl:value-of select="concat($linkprefix,substring-before(@href, 'xhp'),'html',$anchor,$linkpostfix)"/></xsl:variable>
+ <a target ="_top" href="{$href}"><xsl:apply-templates /></a>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="href"><xsl:value-of select="concat($linkprefix,substring-before(@href, 'xhp'),'html',$linkpostfix)"/></xsl:variable>
+ <a target ="_top" href="{$href}"><xsl:apply-templates /></a>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- Insert Note, Warning, or Tip -->
+<xsl:template name="insertnote">
+ <xsl:param name="type" /> <!-- note, tip, or warning -->
+ <xsl:variable name="imgsrc">
+ <xsl:choose>
+ <xsl:when test="$type='note'"><xsl:value-of select="$note_img"/></xsl:when>
+ <xsl:when test="$type='tip'"><xsl:value-of select="$tip_img"/></xsl:when>
+ <xsl:when test="$type='warning'"><xsl:value-of select="$warning_img"/></xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="alt">
+ <xsl:variable name="href"><xsl:value-of select="$alttext"/></xsl:variable>
+ <xsl:variable name="anchor"><xsl:value-of select="concat('alt_',$type)"/></xsl:variable>
+ <xsl:variable name="doc" select="document($href)"/>
+ <xsl:apply-templates select="$doc//variable[@id=$anchor]" mode="embedded"/>
+ </xsl:variable>
+ <div class="{$type}">
+ <div class="noteicon"><img src="{$imgsrc}" alt="{$alt}" title="{$alt}" style="{$iconsizestyle}"/></div>
+ <div class="notetext"><p><xsl:apply-templates /></p></div>
+ </div>
+ <br/>
+</xsl:template>
+
+<!-- Insert a heading -->
+<xsl:template name="insertheading">
+ <xsl:param name="level" />
+ <xsl:param name="embedded" />
+ <xsl:element name="{concat('h',$level)}">
+ <xsl:if test="$level = '1' or $level='2'">
+ <xsl:attribute name="itemprop"><xsl:text>articleSection</xsl:text></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$embedded = 'yes'">
+ <xsl:apply-templates mode="embedded"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+</xsl:template>
+
+<!-- Evaluate a case or caseinline switch -->
+<xsl:template name="insertcase">
+ <xsl:param name="embedded" />
+ <xsl:variable name="auxID" select="concat(@select,generate-id())"/>
+ <xsl:choose>
+ <xsl:when test="$embedded = 'yes'">
+ <span hidden="true" id="{$auxID}" class="{@select}"><xsl:apply-templates mode="embedded"/></span>
+ </xsl:when>
+ <xsl:otherwise>
+ <span hidden="true" id="{$auxID}" class="{@select}"><xsl:apply-templates/></span>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- Evaluate a default or defaultinline switch -->
+<xsl:template name="insertdefault">
+ <xsl:param name="embedded" />
+ <xsl:choose>
+ <xsl:when test="parent::switch[@select='sys'] or parent::switchinline[@select='sys']">
+ <xsl:variable name="auxID" select="concat('default',generate-id())"/>
+ <xsl:choose>
+ <xsl:when test="$embedded = 'yes'">
+ <span hidden="true" id="{$auxID}"><xsl:apply-templates mode="embedded"/></span>
+ </xsl:when>
+ <xsl:otherwise>
+ <span hidden="true" id="{$auxID}"><xsl:apply-templates /></span>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="parent::switch[@select='appl'] or parent::switchinline[@select='appl']">
+ <xsl:variable name="auxID" select="concat('default',generate-id())"/>
+ <xsl:choose>
+ <xsl:when test="$embedded = 'yes'">
+ <span hidden="true" id="{$auxID}"><xsl:apply-templates mode="embedded"/></span>
+ </xsl:when>
+ <xsl:otherwise>
+ <span hidden="true" id="{$auxID}"><xsl:apply-templates /></span>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="parent::switch[@select='distrib'] or parent::switchinline[@select='distrib']"><!--TODO: fix this distrib case if relevant-->
+ <xsl:if test="not(../child::case[@select=$distrib]) and not(../child::caseinline[@select=$distrib])">
+ <xsl:choose>
+ <xsl:when test="$embedded = 'yes'">
+ <span hidden="true" itemprop="distrib" value="DEFDIST"><xsl:apply-templates mode="embedded"/></span>
+ </xsl:when>
+ <xsl:otherwise>
+ <span hidden="true" itemprop="distrib" value="DEFDIST"><xsl:apply-templates /></span>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:when>
+ </xsl:choose>
+</xsl:template>
+
+<!-- evaluate embeds -->
+<xsl:template name="insertembed">
+ <xsl:param name="doc" />
+ <xsl:param name="anchor" />
+ <!-- different embed targets (also falsely used embed instead embedvar) -->
+ <xsl:choose>
+ <xsl:when test="$doc//section[@id=$anchor]"> <!-- first test for a section of that name -->
+ <xsl:apply-templates select="$doc//section[@id=$anchor]" mode="embedded"/>
+ </xsl:when>
+ <xsl:when test="$doc//paragraph[@id=$anchor]"> <!-- then test for a para of that name -->
+ <p class="embedded">
+ <xsl:apply-templates select="$doc//paragraph[@id=$anchor]" mode="embedded"/>
+ </p>
+ </xsl:when>
+ <xsl:when test="$doc//variable[@id=$anchor]"> <!-- then test for a variable of that name -->
+ <p class="embedded">
+ <xsl:apply-templates select="$doc//variable[@id=$anchor]" mode="embedded"/>
+ </p>
+ </xsl:when>
+ <xsl:otherwise> <!-- then give up -->
+ <p class="bug">D'oh! You found a bug (<xsl:value-of select="@href"/> not found).</p>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- Insert an image -->
+<xsl:template name="insertimage">
+ <xsl:variable name="src2">
+ <xsl:choose>
+ <xsl:when test="starts-with(@src,'media/screenshots/')">
+ <xsl:choose>
+ <xsl:when test="not(@localize=false) and not($lang='en-US')">
+ <xsl:variable name="tmp0" select="substring-before(@src, '/ui/')"/>
+ <xsl:variable name="tmp1" select="substring-after(@src, '/ui/')"/>
+ <xsl:variable name="tmp2" select="substring-before($tmp1,'/')"/>
+ <xsl:variable name="tmp3" select="substring-after($tmp1,'/')"/>
+ <xsl:value-of select="concat($tmp0,'/ui/', $tmp2, '/',$lang,'/',$tmp3)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@src"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <!-- generic media file -->
+ <xsl:when test="starts-with(@src,'media/')">
+ <xsl:value-of select="@src"/>
+ </xsl:when>
+ <!-- handle icons -->
+ <xsl:when test="not(starts-with(@src,'media/'))">
+ <xsl:variable name="linklist">
+ <xsl:call-template name="linktxt"><xsl:with-param name="src1" select="@src"/></xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="aux00">
+ <xsl:choose>
+ <xsl:when test="substring($linklist,string-length($linklist) - 3, 4)='.png'">
+ <xsl:value-of select="concat(substring-before($linklist,'.png'),'.svg')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$linklist"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="concat('media/icon-themes/',$aux00)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@src"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="imagestyle">
+ <xsl:choose>
+ <xsl:when test="starts-with(@src,'media/screenshots/')">
+ <xsl:value-of select="'screenshot'"/>
+ </xsl:when>
+ <xsl:when test="starts-with(@src,'media/')">
+ <xsl:value-of select="'genericimage'"/>
+ </xsl:when>
+ <xsl:when test="not(starts-with(@src,'media/'))">
+ <xsl:value-of select="'iconimage'"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'genericimage'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="alt"><xsl:value-of select="./alt"/></xsl:variable>
+ <xsl:variable name="width">
+ <xsl:if test="string-length(@width)!=0">
+ <xsl:call-template name="convert2px"><xsl:with-param name="value" select="@width"/></xsl:call-template>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="height">
+ <xsl:if test="string-length(@height)!=0">
+ <xsl:call-template name="convert2px"><xsl:with-param name="value" select="@height"/></xsl:call-template>
+ </xsl:if>
+ </xsl:variable>
+ <img src="{$src2}" class="{$imagestyle}" alt="{$alt}" title="{$alt}" style="{concat('width:',$width,';height:',$height)}"/>
+</xsl:template>
+
+<!-- Insert an object -->
+<xsl:template name="insertobject">
+ <xsl:variable name="tmp_href"><xsl:value-of select="concat($urlpre,'text/shared/00/00000004.xhp')"/></xsl:variable>
+ <xsl:variable name="tmp_doc" select="document($tmp_href)"/>
+ <xsl:variable name="data">
+ <xsl:value-of select="concat($img_url_prefix,@data)"/>
+ </xsl:variable>
+ <xsl:variable name="type"><xsl:value-of select="@type"/></xsl:variable>
+ <xsl:variable name="width">
+ <xsl:call-template name="convert2px"><xsl:with-param name="value" select="@width"/></xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="height">
+ <xsl:call-template name="convert2px"><xsl:with-param name="value" select="@height"/></xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="auxID" select="concat('obj',generate-id())"/>
+ <xsl:choose>
+ <xsl:when test="starts-with(@type,'video/youtube')">
+ <div id="mediadiv">
+ <iframe id="{@id}" src="{@data}" width="{$width}" height="{$height}" frameborder="0" allowfullscreen="true"></iframe>
+ </div>
+ </xsl:when>
+ <xsl:when test="not(starts-with(@type,'video/youtube')) and starts-with(@type,'video')">
+ <div id="mediadiv">
+ <video src="{$data}" type="{@type}" width="{$width}" height="{$height}" controls="'1'"></video>
+ </div>
+ </xsl:when>
+ <xsl:when test="starts-with(@type,'audio')">
+ <div id="mediadiv">
+ <audio src="{$data}" type="{@type}" controls="'1'"></audio>
+ </div>
+ </xsl:when>
+ <xsl:when test="@type='application/vnd.oasis.opendocument.spreadsheet'">
+ <xsl:variable name="src">
+ <xsl:call-template name="addlang2path">
+ <xsl:with-param name="string" select="@data"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <div class="samplefilesection" id="{$auxID}">
+ <h3><xsl:apply-templates select="$tmp_doc//variable[@id='samplefile']"/></h3>
+ <a class="objectfiles" href="{$src}"><img src="media/navigation/libo-calc.svg" width="25px" height="30px"></img></a>
+ </div>
+ </xsl:when>
+ <xsl:when test="@type='application/vnd.oasis.opendocument.text'">
+ <xsl:variable name="src">
+ <xsl:call-template name="addlang2path">
+ <xsl:with-param name="string" select="@data"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <div class="samplefilesection" id="{$auxID}">
+ <h3><xsl:apply-templates select="$tmp_doc//variable[@id='samplefile']"/></h3>
+ <a class="objectfiles" href="{$src}"><img src="media/navigation/libo-writer.svg" width="25px" height="30px"></img></a>
+ </div>
+ </xsl:when>
+ <xsl:when test="@type='application/vnd.oasis.opendocument.presentation'">
+ <xsl:variable name="src">
+ <xsl:call-template name="addlang2path">
+ <xsl:with-param name="string" select="@data"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <div class="samplefilesection" id="{$auxID}">
+ <h3><xsl:apply-templates select="$tmp_doc//variable[@id='samplefile']"/></h3>
+ <a class="objectfiles" href="{$src}"><img src="media/navigation/libo-impress.svg" width="25px" height="30px"></img></a>
+ </div>
+ </xsl:when>
+ <xsl:when test="@type='application/vnd.oasis.opendocument.drawing'">
+ <xsl:variable name="src">
+ <xsl:call-template name="addlang2path">
+ <xsl:with-param name="string" select="@data"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <div class="samplefilesection" id="{$auxID}">
+ <h3><xsl:apply-templates select="$tmp_doc//variable[@id='samplefile']"/></h3>
+ <a class="objectfiles" href="{$src}"><img src="media/navigation/libo-draw.svg" width="25px" height="30px"></img></a>
+ </div>
+ </xsl:when>
+ <xsl:when test="@type='application/vnd.oasis.opendocument.formula'">
+ <xsl:variable name="src">
+ <xsl:call-template name="addlang2path">
+ <xsl:with-param name="string" select="@data"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <div class="samplefilesection" id="{$auxID}">
+ <h3><xsl:apply-templates select="$tmp_doc//variable[@id='samplefile']"/></h3>
+ <a class="objectfiles" href="{$src}"><img src="media/navigation/libo-math.svg" width="25px" height="30px"></img></a>
+ </div>
+ </xsl:when>
+ <xsl:when test="@type='application/vnd.oasis.opendocument.database'">
+ <xsl:variable name="src">
+ <xsl:call-template name="addlang2path">
+ <xsl:with-param name="string" select="@data"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <div class="samplefilesection" id="{$auxID}">
+ <h3><xsl:apply-templates select="$tmp_doc//variable[@id='samplefile']"/></h3>
+ <a class="objectfiles" href="{$src}"><img src="media/navigation/libo-base.svg" width="25px" height="30px"></img></a>
+ </div>
+ </xsl:when>
+ <xsl:otherwise>
+ <object width="{$width}" height="{$height}" data="{$data}" type="{@type}"></object>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- changing measure to pixel -->
+<xsl:template name="convert2px">
+ <xsl:param name="value"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="concat(round(number(substring-before($value, 'cm')) * $dpcm),'px')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="concat(round(number(substring-before($value, 'mm')) * $dpmm),'px')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="concat(round(number(substring-before($value, 'in')) * $dpi),'px')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="$value"/>
+ </xsl:when>
+ <xsl:otherwise>
+<!-- <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'px'!</xsl:message> -->
+ <xsl:value-of select="concat($value, 'px;')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- Insert a Table -->
+<xsl:template name="inserttable">
+ <xsl:variable name="imgsrc"> <!-- see if we are in an image table -->
+ <xsl:value-of select="tablerow/tablecell[1]/paragraph[1]/image/@src"/>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="count(descendant::tablecell)=1">
+ <div class="onecell"><xsl:apply-templates mode="onecell"/></div>
+ </xsl:when>
+
+ <xsl:when test="descendant::tablecell[1]/descendant::image">
+ <xsl:apply-templates mode="icontable"/>
+ </xsl:when>
+
+ <xsl:when test="@class='wide'">
+ <table border="1" class="{@class}" cellpadding="0" cellspacing="0" width="100%" >
+ <xsl:apply-templates />
+ </table>
+ <br/>
+ </xsl:when>
+
+ <xsl:when test="not(@class='')">
+ <table border="1" class="{@class}" cellpadding="0" cellspacing="0" >
+ <xsl:apply-templates />
+ </table>
+ <br/>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <table border="1" class="border" cellpadding="0" cellspacing="0" >
+ <xsl:apply-templates />
+ </table>
+ <br/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template name="resolveembed">
+ <div class="embedded">
+ <xsl:variable name="href"><xsl:value-of select="concat($urlpre,substring-before(@href,'#'))"/></xsl:variable>
+ <xsl:variable name="anc"><xsl:value-of select="substring-after(@href,'#')"/></xsl:variable>
+ <xsl:variable name="docum" select="document($href)"/>
+ <xsl:call-template name="insertembed">
+ <xsl:with-param name="doc" select="$docum" />
+ <xsl:with-param name="anchor" select="$anc" />
+ </xsl:call-template>
+ </div>
+</xsl:template>
+
+<xsl:template name="resolveembedvar">
+ <xsl:if test="not(@href='text/shared/00/00000004.xhp#wie')"> <!-- special treatment if howtoget links -->
+ <xsl:variable name="archive"><xsl:value-of select="concat(substring-before(substring-after(@href,'text/'),'/'),'/')"/></xsl:variable>
+ <xsl:variable name="href"><xsl:value-of select="concat($urlpre,substring-before(@href,'#'))"/></xsl:variable>
+ <xsl:variable name="anchor"><xsl:value-of select="substring-after(@href,'#')"/></xsl:variable>
+ <xsl:variable name="doc" select="document($href)"/>
+ <xsl:choose>
+ <xsl:when test="$doc//variable[@id=$anchor]"> <!-- test for a variable of that name -->
+ <xsl:apply-templates select="$doc//variable[@id=$anchor]" mode="embedded"/>
+ </xsl:when>
+ <xsl:otherwise> <!-- or give up -->
+ <span class="bug">[<xsl:value-of select="@href"/> not found].</span>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+</xsl:template>
+
+<!-- Apply -->
+<xsl:template name="apply">
+ <xsl:param name="embedded" />
+ <xsl:choose>
+ <xsl:when test="$embedded = 'yes'">
+ <xsl:apply-templates mode="embedded"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates />
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template name="filehtml">
+ <xsl:param name="file"/>
+ <xsl:value-of select="concat(substring-before($file,'.xhp'),'.html')"/>
+</xsl:template>
+
+<!-- recursive named template -->
+<xsl:template name="tokenize">
+ <xsl:param name="str" />
+ <xsl:param name="result" select="''" />
+ <xsl:choose>
+ <xsl:when test="substring-after($str,'/')">
+ <xsl:call-template name="tokenize">
+ <xsl:with-param name="str" select="substring-after($str,'/')" />
+ <xsl:with-param name="result" select="concat($result,'../')" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$result" />
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+<!--Add language to path for file -->
+<xsl:template name="addlang2path">
+ <xsl:param name="string"/>
+ <xsl:choose>
+ <xsl:when test="not($lang='en-US')">
+ <xsl:variable name="tmpfn">
+ <xsl:call-template name="substring-after-last">
+ <xsl:with-param name="string" select="$string"/>
+ <xsl:with-param name="char" select="'/'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat(substring-before($string, $tmpfn),$lang,'/',$tmpfn)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$string"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template name="substring-after-last">
+ <xsl:param name="string"/>
+ <xsl:param name="char"/>
+ <xsl:choose>
+ <xsl:when test="contains($string, $char)">
+ <xsl:call-template name="substring-after-last">
+ <xsl:with-param name="string" select="substring-after($string, $char)"/>
+ <xsl:with-param name="char" select="$char"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$string"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/helpcontent2/help3xsl/paginathing.js b/helpcontent2/help3xsl/paginathing.js
new file mode 100644
index 000000000..cd52b3637
--- /dev/null
+++ b/helpcontent2/help3xsl/paginathing.js
@@ -0,0 +1,243 @@
+/**
+ * Paginathing
+ * Paginate Everything
+ *
+ * Original author Alfred Crosby <https://github.com/alfredcrosby>
+ * Inspired from http://esimakin.github.io/twbs-pagination/
+ * Modified to pure JavaScript and specialised to LibreOffice Help by
+ * Ilmari Lauhakangas
+ *
+ * MIT License (Expat)
+ *
+ * Copyright (c) 2018 Alfred Crosby
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+var options = {
+ perPage: 20,
+ limitPagination: 6,
+ prevNext: true,
+ firstLast: true,
+ prevText: '←',
+ nextText: '→',
+ firstText: '⇤',
+ lastText: '⇥',
+ containerClass: 'pagination-container',
+ ulClass: 'pagination',
+ liClass: 'page',
+ activeClass: 'active',
+ disabledClass: 'disabled'
+};
+
+var Paginator = function(element) {
+ var el = element;
+ var startPage = 1;
+ var currentPage = 1;
+ var pageDivision = 0;
+ var totalItems = el.children.length;
+ var limitPagination = options.limitPagination;
+ pageDivision = Math.ceil(totalItems / options.perPage);
+ // let's not display pagination leading nowhere
+ function pagLimit() {
+ if (options.limitPagination >= pageDivision) {
+ limitPagination = pageDivision;
+ } else {
+ limitPagination = options.limitPagination;
+ }
+ return limitPagination;
+ }
+ var totalPages = Math.max(pageDivision, pagLimit());
+ var existingContainer = document.getElementsByClassName('pagination-container')[0];
+ if (existingContainer) {
+ parent = existingContainer.parentNode;
+ parent.removeChild(existingContainer);
+ }
+ var container = document.createElement('nav');
+ container.setAttribute('class', options.containerClass);
+ var ul = document.createElement('ul');
+ ul.setAttribute('class', options.ulClass);
+
+ function paginationFunc(type, page) {
+ var li = document.createElement('li');
+ var a = document.createElement('a');
+ a.setAttribute('href', '#');
+ var cssClass = type === 'number' ? options.liClass : type;
+ var text = document.createTextNode(type === 'number' ? page : paginationText(type));
+
+ li.classList.add(cssClass);
+ li.setAttribute('data-pagination-type', type);
+ li.setAttribute('data-page', page);
+ a.appendChild(text);
+ li.appendChild(a);
+
+ return li;
+ }
+
+ function paginationText(type) {
+ return options[type + 'Text'];
+ }
+
+ function buildPagination() {
+ var pagination = [];
+ var prev = currentPage - 1 < startPage ? startPage : currentPage - 1;
+ var next = currentPage + 1 > totalPages ? totalPages : currentPage + 1;
+
+ var start = 0;
+ var end = 0;
+ var limit = limitPagination;
+
+ if (limit) {
+ if (currentPage <= Math.ceil(limit / 2) + 1) {
+ start = 1;
+ end = limit;
+ } else if (currentPage + Math.floor(limit / 2) >= totalPages) {
+ start = totalPages + 1 - limit;
+ end = totalPages;
+ } else {
+ start = currentPage - Math.ceil(limit / 2);
+ end = currentPage + Math.floor(limit / 2);
+ }
+ } else {
+ start = startPage;
+ end = totalPages;
+ }
+
+
+ // "First" button
+ if (options.firstLast) {
+ pagination.push(paginationFunc('first', startPage));
+ }
+
+ // "Prev" button
+ if (options.prevNext) {
+ pagination.push(paginationFunc('prev', prev));
+ }
+
+ // Pagination
+ for (var i = start; i <= end; i++) {
+ pagination.push(paginationFunc('number', i));
+ }
+
+ // "Next" button
+ if (options.prevNext) {
+ pagination.push(paginationFunc('next', next));
+ }
+
+ // "Last" button
+ if (options.firstLast) {
+ pagination.push(paginationFunc('last', totalPages));
+ }
+ return pagination;
+ }
+
+ function render(page) {
+ // Remove children before re-render (prevent duplicate)
+ while (ul.hasChildNodes()) {
+ ul.removeChild(ul.lastChild);
+ }
+
+ var paginationBuild = buildPagination();
+
+ paginationBuild.forEach(function(item) {
+ ul.appendChild(item);
+ });
+
+ // Manage active DOM
+ var startAt = page === 1 ? 0 : (page - 1) * options.perPage;
+ var endAt = page * options.perPage;
+
+ var domLi = el.children;
+
+ for (var i = 0, len = domLi.length; i < len; i++) {
+ var item = domLi[i];
+
+ if (i >= startAt && i <= endAt) {
+ item.classList.remove('hidden');
+ } else {
+ item.classList.add('hidden');
+ }
+ }
+
+ // Manage active state
+ var ulKids = ul.getElementsByTagName("li");
+
+ for (var i = 0, len = ulKids.length; i < len; i++) {
+ var _li = ulKids[i];
+ var type = _li.getAttribute('data-pagination-type');
+
+ switch (type) {
+ case 'number':
+ if (parseInt(_li.getAttribute('data-page'), 10) === page) {
+ _li.classList.add(options.activeClass);
+ }
+ break;
+ case 'first':
+ page === startPage && _li.classList.toggle(options.disabledClass);
+ break;
+ case 'last':
+ page === totalPages && _li.classList.toggle(options.disabledClass);
+ break;
+ case 'prev':
+ (page - 1) < startPage && _li.classList.toggle(options.disabledClass);
+ break;
+ case 'next':
+ (page + 1) > totalPages && _li.classList.toggle(options.disabledClass);
+ break;
+ default:
+ break;
+ }
+ }
+
+ el.before(container);
+ container.appendChild(ul);
+ }
+
+ function handle() {
+ var pagLi = container.childNodes[0].childNodes;
+
+ for (var i = 0, len = pagLi.length; i < len; i++) {
+ (function() {
+ var item = pagLi[i];
+
+ item.addEventListener('click', function(e) {
+ e.preventDefault();
+ var page = parseInt(item.getAttribute('data-page'), 10);
+ currentPage = page;
+ // let's prevent the pagination from flowing to two rows
+ if (currentPage >= 98) {
+ limitPagination = 4;
+ } else {
+ limitPagination = pagLimit();
+ }
+ show(page);
+ });
+ }());
+ }
+ }
+
+ function show(page) {
+ render(page);
+ handle();
+ }
+
+ show(startPage);
+
+ return;
+};
diff --git a/helpcontent2/help3xsl/polyfills.js b/helpcontent2/help3xsl/polyfills.js
new file mode 100644
index 000000000..0c14764d7
--- /dev/null
+++ b/helpcontent2/help3xsl/polyfills.js
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+// This file can be removed, when we stop supporting IE11.
+// Polyfill for .before()
+// from: https://github.com/jserz/js_piece/blob/master/DOM/ChildNode/before()/before().md
+// Copyright (c) 2016-present, jszhou
+// MIT License
+(function (arr) {
+ arr.forEach(function (item) {
+ if (item.hasOwnProperty('before')) {
+ return;
+ }
+ Object.defineProperty(item, 'before', {
+ configurable: true,
+ enumerable: true,
+ writable: true,
+ value: function before() {
+ var argArr = Array.prototype.slice.call(arguments),
+ docFrag = document.createDocumentFragment();
+
+ argArr.forEach(function (argItem) {
+ var isNode = argItem instanceof Node;
+ docFrag.appendChild(isNode ? argItem : document.createTextNode(String(argItem)));
+ });
+
+ this.parentNode.insertBefore(docFrag, this);
+ }
+ });
+ });
+})([Element.prototype, CharacterData.prototype, DocumentType.prototype]);
+// Polyfill for .startsWith()
+// from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith#Polyfill
+if (!String.prototype.startsWith) {
+ Object.defineProperty(String.prototype, 'startsWith', {
+ value: function(search, pos) {
+ pos = !pos || pos < 0 ? 0 : +pos;
+ return this.substring(pos, pos + search.length) === search;
+ }
+ });
+}
+// Polyfill for .matches()
+// from: https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill
+if (!Element.prototype.matches) {
+ Element.prototype.matches = Element.prototype.msMatchesSelector ||
+ Element.prototype.webkitMatchesSelector;
+}
+// Polyfill for iterable Set (IE11)
+// from: https://stackoverflow.com/a/45686452/3057764
+if (new Set([0]).size === 0) {
+ //constructor doesn't take an iterable as an argument - thanks IE
+ const BuiltinSet = Set;
+ Set = function Set(iterable) {
+ const set = new BuiltinSet();
+ if (iterable) {
+ iterable.forEach(set.add, set);
+ }
+ return set;
+ };
+ Set.prototype = BuiltinSet.prototype;
+ Set.prototype.constructor = Set;
+}
+// Polyfill for using :scope in querySelector/querySelectorAll
+// from: https://github.com/lazd/scopedQuerySelectorShim
+// Copyright (C) 2015 Larry Davis
+// This software may be modified and distributed under the terms of the BSD license.
+(function() {
+ if (!HTMLElement.prototype.querySelectorAll) {
+ throw new Error("rootedQuerySelectorAll: This polyfill can only be used with browsers that support querySelectorAll");
+ }
+ // A temporary element to query against for elements not currently in the DOM
+ // We'll also use this element to test for :scope support
+ var container = document.createElement("div");
+ // Check if the browser supports :scope
+ try {
+ // Browser supports :scope, do nothing
+ container.querySelectorAll(":scope *");
+ } catch (e) {
+ // Match usage of scope
+ var scopeRE = /^\s*:scope/gi;
+ // Overrides
+ function overrideNodeMethod(prototype, methodName) {
+ // Store the old method for use later
+ var oldMethod = prototype[methodName];
+ // Override the method
+ prototype[methodName] = function(query) {
+ var nodeList, gaveId = false, gaveContainer = false;
+ if (query.match(scopeRE)) {
+ // Remove :scope
+ query = query.replace(scopeRE, "");
+ if (!this.parentNode) {
+ // Add to temporary container
+ container.appendChild(this);
+ gaveContainer = true;
+ }
+ parentNode = this.parentNode;
+ if (!this.id) {
+ // Give temporary ID
+ this.id = "rootedQuerySelector_id_" + new Date().getTime();
+ gaveId = true;
+ }
+ // Find elements against parent node
+ nodeList = oldMethod.call(parentNode, "#" + this.id + " " + query);
+ // Reset the ID
+ if (gaveId) {
+ this.id = "";
+ }
+ // Remove from temporary container
+ if (gaveContainer) {
+ container.removeChild(this);
+ }
+ return nodeList;
+ } else {
+ // No immediate child selector used
+ return oldMethod.call(this, query);
+ }
+ };
+ }
+ // Browser doesn't support :scope, add polyfill
+ overrideNodeMethod(HTMLElement.prototype, "querySelector");
+ overrideNodeMethod(HTMLElement.prototype, "querySelectorAll");
+ }
+})();
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/helpcontent2/help3xsl/prism.css b/helpcontent2/help3xsl/prism.css
new file mode 100644
index 000000000..8bd96d9cc
--- /dev/null
+++ b/helpcontent2/help3xsl/prism.css
@@ -0,0 +1,270 @@
+/* PrismJS 1.20.0
+https://prismjs.com/download.html#themes=prism-coy&languages=markup+css+clike+javascript+python+visual-basic&plugins=line-numbers+normalize-whitespace */
+/**
+ * prism.js Coy theme for JavaScript, CoffeeScript, CSS and HTML
+ * Based on https://github.com/tshedor/workshop-wp-theme (Example: http://workshop.kansan.com/category/sessions/basics or http://workshop.timshedor.com/category/sessions/basics);
+ * @author Tim Shedor
+ */
+
+code[class*="language-"],
+pre[class*="language-"] {
+ color: black;
+ background: none;
+ font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+ font-size: 1em;
+ text-align: left;
+ white-space: pre;
+ word-spacing: normal;
+ word-break: normal;
+ word-wrap: normal;
+ line-height: 1.5;
+
+ -moz-tab-size: 4;
+ -o-tab-size: 4;
+ tab-size: 4;
+
+ -webkit-hyphens: none;
+ -moz-hyphens: none;
+ -ms-hyphens: none;
+ hyphens: none;
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+ position: relative;
+ margin: .5em 0;
+ overflow: visible;
+ padding: 0;
+}
+pre[class*="language-"]>code {
+ position: relative;
+ border-left: 10px solid #358ccb;
+ box-shadow: -1px 0px 0px 0px #358ccb, 0px 0px 0px 1px #dfdfdf;
+ background-color: #fdfdfd;
+ background-image: linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%);
+ background-size: 3em 3em;
+ background-origin: content-box;
+ background-attachment: local;
+}
+
+code[class*="language"] {
+ max-height: inherit;
+ height: inherit;
+ padding: 0 1em;
+ display: block;
+ overflow: auto;
+}
+
+/* Margin bottom to accommodate shadow */
+:not(pre) > code[class*="language-"],
+pre[class*="language-"] {
+ background-color: #fdfdfd;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ margin-bottom: 1em;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+ position: relative;
+ padding: .2em;
+ border-radius: 0.3em;
+ color: #c92c2c;
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ display: inline;
+ white-space: normal;
+}
+
+pre[class*="language-"]:before,
+pre[class*="language-"]:after {
+ content: '';
+ z-index: -2;
+ display: block;
+ position: absolute;
+ bottom: 0.75em;
+ left: 0.18em;
+ width: 40%;
+ height: 20%;
+ max-height: 13em;
+ box-shadow: 0px 13px 8px #979797;
+ -webkit-transform: rotate(-2deg);
+ -moz-transform: rotate(-2deg);
+ -ms-transform: rotate(-2deg);
+ -o-transform: rotate(-2deg);
+ transform: rotate(-2deg);
+}
+
+:not(pre) > code[class*="language-"]:after,
+pre[class*="language-"]:after {
+ right: 0.75em;
+ left: auto;
+ -webkit-transform: rotate(2deg);
+ -moz-transform: rotate(2deg);
+ -ms-transform: rotate(2deg);
+ -o-transform: rotate(2deg);
+ transform: rotate(2deg);
+}
+
+.token.comment,
+.token.block-comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+ color: #7D8B99;
+}
+
+.token.punctuation {
+ color: #5F6364;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number,
+.token.function-name,
+.token.constant,
+.token.symbol,
+.token.deleted {
+ color: #c92c2c;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string,
+.token.char,
+.token.function,
+.token.builtin,
+.token.inserted {
+ color: #2f9c0a;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.token.variable {
+ color: #a67f59;
+ background: rgba(255, 255, 255, 0.5);
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword,
+.token.class-name {
+ color: #1990b8;
+}
+
+.token.regex,
+.token.important {
+ color: #e90;
+}
+
+.language-css .token.string,
+.style .token.string {
+ color: #a67f59;
+ background: rgba(255, 255, 255, 0.5);
+}
+
+.token.important {
+ font-weight: normal;
+}
+
+.token.bold {
+ font-weight: bold;
+}
+.token.italic {
+ font-style: italic;
+}
+
+.token.entity {
+ cursor: help;
+}
+
+.token.namespace {
+ opacity: .7;
+}
+
+@media screen and (max-width: 767px) {
+ pre[class*="language-"]:before,
+ pre[class*="language-"]:after {
+ bottom: 14px;
+ box-shadow: none;
+ }
+
+}
+
+/* Plugin styles */
+.token.tab:not(:empty):before,
+.token.cr:before,
+.token.lf:before {
+ color: #e0d7d1;
+}
+
+/* Plugin styles: Line Numbers */
+pre[class*="language-"].line-numbers.line-numbers {
+ padding-left: 0;
+}
+
+pre[class*="language-"].line-numbers.line-numbers code {
+ padding-left: 3.8em;
+}
+
+pre[class*="language-"].line-numbers.line-numbers .line-numbers-rows {
+ left: 0;
+}
+
+/* Plugin styles: Line Highlight */
+pre[class*="language-"][data-line] {
+ padding-top: 0;
+ padding-bottom: 0;
+ padding-left: 0;
+}
+pre[data-line] code {
+ position: relative;
+ padding-left: 4em;
+}
+pre .line-highlight {
+ margin-top: 0;
+}
+
+pre[class*="language-"].line-numbers {
+ position: relative;
+ padding-left: 3.8em;
+ counter-reset: linenumber;
+}
+
+pre[class*="language-"].line-numbers > code {
+ position: relative;
+ white-space: inherit;
+}
+
+.line-numbers .line-numbers-rows {
+ position: absolute;
+ pointer-events: none;
+ top: 0;
+ font-size: 100%;
+ left: -3.8em;
+ width: 3em; /* works for line-numbers below 1000 lines */
+ letter-spacing: -1px;
+ border-right: 1px solid #999;
+
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+
+}
+
+ .line-numbers-rows > span {
+ display: block;
+ counter-increment: linenumber;
+ }
+
+ .line-numbers-rows > span:before {
+ content: counter(linenumber);
+ color: #999;
+ display: block;
+ padding-right: 0.8em;
+ text-align: right;
+ }
+
diff --git a/helpcontent2/help3xsl/prism.js b/helpcontent2/help3xsl/prism.js
new file mode 100644
index 000000000..108011888
--- /dev/null
+++ b/helpcontent2/help3xsl/prism.js
@@ -0,0 +1,1519 @@
+/* PrismJS 1.20.0
+https://prismjs.com/download.html#themes=prism-coy&languages=markup+css+clike+javascript+python+visual-basic&plugins=line-numbers+normalize-whitespace */
+var _self = (typeof window !== 'undefined')
+ ? window // if in browser
+ : (
+ (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope)
+ ? self // if in worker
+ : {} // if in node js
+ );
+
+/**
+ * Prism: Lightweight, robust, elegant syntax highlighting
+ * MIT license http://www.opensource.org/licenses/mit-license.php/
+ * @author Lea Verou http://lea.verou.me
+ */
+
+var Prism = (function (_self){
+
+// Private helper vars
+var lang = /\blang(?:uage)?-([\w-]+)\b/i;
+var uniqueId = 0;
+
+
+var _ = {
+ manual: _self.Prism && _self.Prism.manual,
+ disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler,
+ util: {
+ encode: function encode(tokens) {
+ if (tokens instanceof Token) {
+ return new Token(tokens.type, encode(tokens.content), tokens.alias);
+ } else if (Array.isArray(tokens)) {
+ return tokens.map(encode);
+ } else {
+ return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/\u00a0/g, ' ');
+ }
+ },
+
+ type: function (o) {
+ return Object.prototype.toString.call(o).slice(8, -1);
+ },
+
+ objId: function (obj) {
+ if (!obj['__id']) {
+ Object.defineProperty(obj, '__id', { value: ++uniqueId });
+ }
+ return obj['__id'];
+ },
+
+ // Deep clone a language definition (e.g. to extend it)
+ clone: function deepClone(o, visited) {
+ var clone, id, type = _.util.type(o);
+ visited = visited || {};
+
+ switch (type) {
+ case 'Object':
+ id = _.util.objId(o);
+ if (visited[id]) {
+ return visited[id];
+ }
+ clone = {};
+ visited[id] = clone;
+
+ for (var key in o) {
+ if (o.hasOwnProperty(key)) {
+ clone[key] = deepClone(o[key], visited);
+ }
+ }
+
+ return clone;
+
+ case 'Array':
+ id = _.util.objId(o);
+ if (visited[id]) {
+ return visited[id];
+ }
+ clone = [];
+ visited[id] = clone;
+
+ o.forEach(function (v, i) {
+ clone[i] = deepClone(v, visited);
+ });
+
+ return clone;
+
+ default:
+ return o;
+ }
+ },
+
+ /**
+ * Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class.
+ *
+ * If no language is set for the element or the element is `null` or `undefined`, `none` will be returned.
+ *
+ * @param {Element} element
+ * @returns {string}
+ */
+ getLanguage: function (element) {
+ while (element && !lang.test(element.className)) {
+ element = element.parentElement;
+ }
+ if (element) {
+ return (element.className.match(lang) || [, 'none'])[1].toLowerCase();
+ }
+ return 'none';
+ },
+
+ /**
+ * Returns the script element that is currently executing.
+ *
+ * This does __not__ work for line script element.
+ *
+ * @returns {HTMLScriptElement | null}
+ */
+ currentScript: function () {
+ if (typeof document === 'undefined') {
+ return null;
+ }
+ if ('currentScript' in document) {
+ return document.currentScript;
+ }
+
+ // IE11 workaround
+ // we'll get the src of the current script by parsing IE11's error stack trace
+ // this will not work for inline scripts
+
+ try {
+ throw new Error();
+ } catch (err) {
+ // Get file src url from stack. Specifically works with the format of stack traces in IE.
+ // A stack will look like this:
+ //
+ // Error
+ // at _.util.currentScript (http://localhost/components/prism-core.js:119:5)
+ // at Global code (http://localhost/components/prism-core.js:606:1)
+
+ var src = (/at [^(\r\n]*\((.*):.+:.+\)$/i.exec(err.stack) || [])[1];
+ if (src) {
+ var scripts = document.getElementsByTagName('script');
+ for (var i in scripts) {
+ if (scripts[i].src == src) {
+ return scripts[i];
+ }
+ }
+ }
+ return null;
+ }
+ }
+ },
+
+ languages: {
+ extend: function (id, redef) {
+ var lang = _.util.clone(_.languages[id]);
+
+ for (var key in redef) {
+ lang[key] = redef[key];
+ }
+
+ return lang;
+ },
+
+ /**
+ * Insert a token before another token in a language literal
+ * As this needs to recreate the object (we cannot actually insert before keys in object literals),
+ * we cannot just provide an object, we need an object and a key.
+ * @param inside The key (or language id) of the parent
+ * @param before The key to insert before.
+ * @param insert Object with the key/value pairs to insert
+ * @param root The object that contains `inside`. If equal to Prism.languages, it can be omitted.
+ */
+ insertBefore: function (inside, before, insert, root) {
+ root = root || _.languages;
+ var grammar = root[inside];
+ var ret = {};
+
+ for (var token in grammar) {
+ if (grammar.hasOwnProperty(token)) {
+
+ if (token == before) {
+ for (var newToken in insert) {
+ if (insert.hasOwnProperty(newToken)) {
+ ret[newToken] = insert[newToken];
+ }
+ }
+ }
+
+ // Do not insert token which also occur in insert. See #1525
+ if (!insert.hasOwnProperty(token)) {
+ ret[token] = grammar[token];
+ }
+ }
+ }
+
+ var old = root[inside];
+ root[inside] = ret;
+
+ // Update references in other language definitions
+ _.languages.DFS(_.languages, function(key, value) {
+ if (value === old && key != inside) {
+ this[key] = ret;
+ }
+ });
+
+ return ret;
+ },
+
+ // Traverse a language definition with Depth First Search
+ DFS: function DFS(o, callback, type, visited) {
+ visited = visited || {};
+
+ var objId = _.util.objId;
+
+ for (var i in o) {
+ if (o.hasOwnProperty(i)) {
+ callback.call(o, i, o[i], type || i);
+
+ var property = o[i],
+ propertyType = _.util.type(property);
+
+ if (propertyType === 'Object' && !visited[objId(property)]) {
+ visited[objId(property)] = true;
+ DFS(property, callback, null, visited);
+ }
+ else if (propertyType === 'Array' && !visited[objId(property)]) {
+ visited[objId(property)] = true;
+ DFS(property, callback, i, visited);
+ }
+ }
+ }
+ }
+ },
+ plugins: {},
+
+ highlightAll: function(async, callback) {
+ _.highlightAllUnder(document, async, callback);
+ },
+
+ highlightAllUnder: function(container, async, callback) {
+ var env = {
+ callback: callback,
+ container: container,
+ selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'
+ };
+
+ _.hooks.run('before-highlightall', env);
+
+ env.elements = Array.prototype.slice.apply(env.container.querySelectorAll(env.selector));
+
+ _.hooks.run('before-all-elements-highlight', env);
+
+ for (var i = 0, element; element = env.elements[i++];) {
+ _.highlightElement(element, async === true, env.callback);
+ }
+ },
+
+ highlightElement: function(element, async, callback) {
+ // Find language
+ var language = _.util.getLanguage(element);
+ var grammar = _.languages[language];
+
+ // Set language on the element, if not present
+ element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
+
+ // Set language on the parent, for styling
+ var parent = element.parentNode;
+ if (parent && parent.nodeName.toLowerCase() === 'pre') {
+ parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
+ }
+
+ var code = element.textContent;
+
+ var env = {
+ element: element,
+ language: language,
+ grammar: grammar,
+ code: code
+ };
+
+ function insertHighlightedCode(highlightedCode) {
+ env.highlightedCode = highlightedCode;
+
+ _.hooks.run('before-insert', env);
+
+ env.element.innerHTML = env.highlightedCode;
+
+ _.hooks.run('after-highlight', env);
+ _.hooks.run('complete', env);
+ callback && callback.call(env.element);
+ }
+
+ _.hooks.run('before-sanity-check', env);
+
+ if (!env.code) {
+ _.hooks.run('complete', env);
+ callback && callback.call(env.element);
+ return;
+ }
+
+ _.hooks.run('before-highlight', env);
+
+ if (!env.grammar) {
+ insertHighlightedCode(_.util.encode(env.code));
+ return;
+ }
+
+ if (async && _self.Worker) {
+ var worker = new Worker(_.filename);
+
+ worker.onmessage = function(evt) {
+ insertHighlightedCode(evt.data);
+ };
+
+ worker.postMessage(JSON.stringify({
+ language: env.language,
+ code: env.code,
+ immediateClose: true
+ }));
+ }
+ else {
+ insertHighlightedCode(_.highlight(env.code, env.grammar, env.language));
+ }
+ },
+
+ highlight: function (text, grammar, language) {
+ var env = {
+ code: text,
+ grammar: grammar,
+ language: language
+ };
+ _.hooks.run('before-tokenize', env);
+ env.tokens = _.tokenize(env.code, env.grammar);
+ _.hooks.run('after-tokenize', env);
+ return Token.stringify(_.util.encode(env.tokens), env.language);
+ },
+
+ tokenize: function(text, grammar) {
+ var rest = grammar.rest;
+ if (rest) {
+ for (var token in rest) {
+ grammar[token] = rest[token];
+ }
+
+ delete grammar.rest;
+ }
+
+ var tokenList = new LinkedList();
+ addAfter(tokenList, tokenList.head, text);
+
+ matchGrammar(text, tokenList, grammar, tokenList.head, 0);
+
+ return toArray(tokenList);
+ },
+
+ hooks: {
+ all: {},
+
+ add: function (name, callback) {
+ var hooks = _.hooks.all;
+
+ hooks[name] = hooks[name] || [];
+
+ hooks[name].push(callback);
+ },
+
+ run: function (name, env) {
+ var callbacks = _.hooks.all[name];
+
+ if (!callbacks || !callbacks.length) {
+ return;
+ }
+
+ for (var i=0, callback; callback = callbacks[i++];) {
+ callback(env);
+ }
+ }
+ },
+
+ Token: Token
+};
+
+_self.Prism = _;
+
+function Token(type, content, alias, matchedStr, greedy) {
+ this.type = type;
+ this.content = content;
+ this.alias = alias;
+ // Copy of the full string this token was created from
+ this.length = (matchedStr || '').length|0;
+ this.greedy = !!greedy;
+}
+
+Token.stringify = function stringify(o, language) {
+ if (typeof o == 'string') {
+ return o;
+ }
+ if (Array.isArray(o)) {
+ var s = '';
+ o.forEach(function (e) {
+ s += stringify(e, language);
+ });
+ return s;
+ }
+
+ var env = {
+ type: o.type,
+ content: stringify(o.content, language),
+ tag: 'span',
+ classes: ['token', o.type],
+ attributes: {},
+ language: language
+ };
+
+ var aliases = o.alias;
+ if (aliases) {
+ if (Array.isArray(aliases)) {
+ Array.prototype.push.apply(env.classes, aliases);
+ } else {
+ env.classes.push(aliases);
+ }
+ }
+
+ _.hooks.run('wrap', env);
+
+ var attributes = '';
+ for (var name in env.attributes) {
+ attributes += ' ' + name + '="' + (env.attributes[name] || '').replace(/"/g, '&quot;') + '"';
+ }
+
+ return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + attributes + '>' + env.content + '</' + env.tag + '>';
+};
+
+/**
+ * @param {string} text
+ * @param {LinkedList<string | Token>} tokenList
+ * @param {any} grammar
+ * @param {LinkedListNode<string | Token>} startNode
+ * @param {number} startPos
+ * @param {boolean} [oneshot=false]
+ * @param {string} [target]
+ */
+function matchGrammar(text, tokenList, grammar, startNode, startPos, oneshot, target) {
+ for (var token in grammar) {
+ if (!grammar.hasOwnProperty(token) || !grammar[token]) {
+ continue;
+ }
+
+ var patterns = grammar[token];
+ patterns = Array.isArray(patterns) ? patterns : [patterns];
+
+ for (var j = 0; j < patterns.length; ++j) {
+ if (target && target == token + ',' + j) {
+ return;
+ }
+
+ var pattern = patterns[j],
+ inside = pattern.inside,
+ lookbehind = !!pattern.lookbehind,
+ greedy = !!pattern.greedy,
+ lookbehindLength = 0,
+ alias = pattern.alias;
+
+ if (greedy && !pattern.pattern.global) {
+ // Without the global flag, lastIndex won't work
+ var flags = pattern.pattern.toString().match(/[imsuy]*$/)[0];
+ pattern.pattern = RegExp(pattern.pattern.source, flags + 'g');
+ }
+
+ pattern = pattern.pattern || pattern;
+
+ for ( // iterate the token list and keep track of the current token/string position
+ var currentNode = startNode.next, pos = startPos;
+ currentNode !== tokenList.tail;
+ pos += currentNode.value.length, currentNode = currentNode.next
+ ) {
+
+ var str = currentNode.value;
+
+ if (tokenList.length > text.length) {
+ // Something went terribly wrong, ABORT, ABORT!
+ return;
+ }
+
+ if (str instanceof Token) {
+ continue;
+ }
+
+ var removeCount = 1; // this is the to parameter of removeBetween
+
+ if (greedy && currentNode != tokenList.tail.prev) {
+ pattern.lastIndex = pos;
+ var match = pattern.exec(text);
+ if (!match) {
+ break;
+ }
+
+ var from = match.index + (lookbehind && match[1] ? match[1].length : 0);
+ var to = match.index + match[0].length;
+ var p = pos;
+
+ // find the node that contains the match
+ p += currentNode.value.length;
+ while (from >= p) {
+ currentNode = currentNode.next;
+ p += currentNode.value.length;
+ }
+ // adjust pos (and p)
+ p -= currentNode.value.length;
+ pos = p;
+
+ // the current node is a Token, then the match starts inside another Token, which is invalid
+ if (currentNode.value instanceof Token) {
+ continue;
+ }
+
+ // find the last node which is affected by this match
+ for (
+ var k = currentNode;
+ k !== tokenList.tail && (p < to || (typeof k.value === 'string' && !k.prev.value.greedy));
+ k = k.next
+ ) {
+ removeCount++;
+ p += k.value.length;
+ }
+ removeCount--;
+
+ // replace with the new match
+ str = text.slice(pos, p);
+ match.index -= pos;
+ } else {
+ pattern.lastIndex = 0;
+
+ var match = pattern.exec(str);
+ }
+
+ if (!match) {
+ if (oneshot) {
+ break;
+ }
+
+ continue;
+ }
+
+ if (lookbehind) {
+ lookbehindLength = match[1] ? match[1].length : 0;
+ }
+
+ var from = match.index + lookbehindLength,
+ match = match[0].slice(lookbehindLength),
+ to = from + match.length,
+ before = str.slice(0, from),
+ after = str.slice(to);
+
+ var removeFrom = currentNode.prev;
+
+ if (before) {
+ removeFrom = addAfter(tokenList, removeFrom, before);
+ pos += before.length;
+ }
+
+ removeRange(tokenList, removeFrom, removeCount);
+
+ var wrapped = new Token(token, inside ? _.tokenize(match, inside) : match, alias, match, greedy);
+ currentNode = addAfter(tokenList, removeFrom, wrapped);
+
+ if (after) {
+ addAfter(tokenList, currentNode, after);
+ }
+
+
+ if (removeCount > 1)
+ matchGrammar(text, tokenList, grammar, currentNode.prev, pos, true, token + ',' + j);
+
+ if (oneshot)
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * @typedef LinkedListNode
+ * @property {T} value
+ * @property {LinkedListNode<T> | null} prev The previous node.
+ * @property {LinkedListNode<T> | null} next The next node.
+ * @template T
+ */
+
+/**
+ * @template T
+ */
+function LinkedList() {
+ /** @type {LinkedListNode<T>} */
+ var head = { value: null, prev: null, next: null };
+ /** @type {LinkedListNode<T>} */
+ var tail = { value: null, prev: head, next: null };
+ head.next = tail;
+
+ /** @type {LinkedListNode<T>} */
+ this.head = head;
+ /** @type {LinkedListNode<T>} */
+ this.tail = tail;
+ this.length = 0;
+}
+
+/**
+ * Adds a new node with the given value to the list.
+ * @param {LinkedList<T>} list
+ * @param {LinkedListNode<T>} node
+ * @param {T} value
+ * @returns {LinkedListNode<T>} The added node.
+ * @template T
+ */
+function addAfter(list, node, value) {
+ // assumes that node != list.tail && values.length >= 0
+ var next = node.next;
+
+ var newNode = { value: value, prev: node, next: next };
+ node.next = newNode;
+ next.prev = newNode;
+ list.length++;
+
+ return newNode;
+}
+/**
+ * Removes `count` nodes after the given node. The given node will not be removed.
+ * @param {LinkedList<T>} list
+ * @param {LinkedListNode<T>} node
+ * @param {number} count
+ * @template T
+ */
+function removeRange(list, node, count) {
+ var next = node.next;
+ for (var i = 0; i < count && next !== list.tail; i++) {
+ next = next.next;
+ }
+ node.next = next;
+ next.prev = node;
+ list.length -= i;
+}
+/**
+ * @param {LinkedList<T>} list
+ * @returns {T[]}
+ * @template T
+ */
+function toArray(list) {
+ var array = [];
+ var node = list.head.next;
+ while (node !== list.tail) {
+ array.push(node.value);
+ node = node.next;
+ }
+ return array;
+}
+
+
+if (!_self.document) {
+ if (!_self.addEventListener) {
+ // in Node.js
+ return _;
+ }
+
+ if (!_.disableWorkerMessageHandler) {
+ // In worker
+ _self.addEventListener('message', function (evt) {
+ var message = JSON.parse(evt.data),
+ lang = message.language,
+ code = message.code,
+ immediateClose = message.immediateClose;
+
+ _self.postMessage(_.highlight(code, _.languages[lang], lang));
+ if (immediateClose) {
+ _self.close();
+ }
+ }, false);
+ }
+
+ return _;
+}
+
+//Get current script and highlight
+var script = _.util.currentScript();
+
+if (script) {
+ _.filename = script.src;
+
+ if (script.hasAttribute('data-manual')) {
+ _.manual = true;
+ }
+}
+
+function highlightAutomaticallyCallback() {
+ if (!_.manual) {
+ _.highlightAll();
+ }
+}
+
+if (!_.manual) {
+ // If the document state is "loading", then we'll use DOMContentLoaded.
+ // If the document state is "interactive" and the prism.js script is deferred, then we'll also use the
+ // DOMContentLoaded event because there might be some plugins or languages which have also been deferred and they
+ // might take longer one animation frame to execute which can create a race condition where only some plugins have
+ // been loaded when Prism.highlightAll() is executed, depending on how fast resources are loaded.
+ // See https://github.com/PrismJS/prism/issues/2102
+ var readyState = document.readyState;
+ if (readyState === 'loading' || readyState === 'interactive' && script && script.defer) {
+ document.addEventListener('DOMContentLoaded', highlightAutomaticallyCallback);
+ } else {
+ if (window.requestAnimationFrame) {
+ window.requestAnimationFrame(highlightAutomaticallyCallback);
+ } else {
+ window.setTimeout(highlightAutomaticallyCallback, 16);
+ }
+ }
+}
+
+return _;
+
+})(_self);
+
+if (typeof module !== 'undefined' && module.exports) {
+ module.exports = Prism;
+}
+
+// hack for components to work correctly in node.js
+if (typeof global !== 'undefined') {
+ global.Prism = Prism;
+}
+;
+Prism.languages.markup = {
+ 'comment': /<!--[\s\S]*?-->/,
+ 'prolog': /<\?[\s\S]+?\?>/,
+ 'doctype': {
+ // https://www.w3.org/TR/xml/#NT-doctypedecl
+ pattern: /<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,
+ greedy: true,
+ inside: {
+ 'internal-subset': {
+ pattern: /(\[)[\s\S]+(?=\]>$)/,
+ lookbehind: true,
+ greedy: true,
+ inside: null // see below
+ },
+ 'string': {
+ pattern: /"[^"]*"|'[^']*'/,
+ greedy: true
+ },
+ 'punctuation': /^<!|>$|[[\]]/,
+ 'doctype-tag': /^DOCTYPE/,
+ 'name': /[^\s<>'"]+/
+ }
+ },
+ 'cdata': /<!\[CDATA\[[\s\S]*?]]>/i,
+ 'tag': {
+ pattern: /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,
+ greedy: true,
+ inside: {
+ 'tag': {
+ pattern: /^<\/?[^\s>\/]+/,
+ inside: {
+ 'punctuation': /^<\/?/,
+ 'namespace': /^[^\s>\/:]+:/
+ }
+ },
+ 'attr-value': {
+ pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,
+ inside: {
+ 'punctuation': [
+ {
+ pattern: /^=/,
+ alias: 'attr-equals'
+ },
+ /"|'/
+ ]
+ }
+ },
+ 'punctuation': /\/?>/,
+ 'attr-name': {
+ pattern: /[^\s>\/]+/,
+ inside: {
+ 'namespace': /^[^\s>\/:]+:/
+ }
+ }
+
+ }
+ },
+ 'entity': [
+ {
+ pattern: /&[\da-z]{1,8};/i,
+ alias: 'named-entity'
+ },
+ /&#x?[\da-f]{1,8};/i
+ ]
+};
+
+Prism.languages.markup['tag'].inside['attr-value'].inside['entity'] =
+ Prism.languages.markup['entity'];
+Prism.languages.markup['doctype'].inside['internal-subset'].inside = Prism.languages.markup;
+
+// Plugin to make entity title show the real entity, idea by Roman Komarov
+Prism.hooks.add('wrap', function (env) {
+
+ if (env.type === 'entity') {
+ env.attributes['title'] = env.content.replace(/&amp;/, '&');
+ }
+});
+
+Object.defineProperty(Prism.languages.markup.tag, 'addInlined', {
+ /**
+ * Adds an inlined language to markup.
+ *
+ * An example of an inlined language is CSS with `<style>` tags.
+ *
+ * @param {string} tagName The name of the tag that contains the inlined language. This name will be treated as
+ * case insensitive.
+ * @param {string} lang The language key.
+ * @example
+ * addInlined('style', 'css');
+ */
+ value: function addInlined(tagName, lang) {
+ var includedCdataInside = {};
+ includedCdataInside['language-' + lang] = {
+ pattern: /(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,
+ lookbehind: true,
+ inside: Prism.languages[lang]
+ };
+ includedCdataInside['cdata'] = /^<!\[CDATA\[|\]\]>$/i;
+
+ var inside = {
+ 'included-cdata': {
+ pattern: /<!\[CDATA\[[\s\S]*?\]\]>/i,
+ inside: includedCdataInside
+ }
+ };
+ inside['language-' + lang] = {
+ pattern: /[\s\S]+/,
+ inside: Prism.languages[lang]
+ };
+
+ var def = {};
+ def[tagName] = {
+ pattern: RegExp(/(<__[\s\S]*?>)(?:<!\[CDATA\[(?:[^\]]|\](?!\]>))*\]\]>|(?!<!\[CDATA\[)[\s\S])*?(?=<\/__>)/.source.replace(/__/g, function () { return tagName; }), 'i'),
+ lookbehind: true,
+ greedy: true,
+ inside: inside
+ };
+
+ Prism.languages.insertBefore('markup', 'cdata', def);
+ }
+});
+
+Prism.languages.html = Prism.languages.markup;
+Prism.languages.mathml = Prism.languages.markup;
+Prism.languages.svg = Prism.languages.markup;
+
+Prism.languages.xml = Prism.languages.extend('markup', {});
+Prism.languages.ssml = Prism.languages.xml;
+Prism.languages.atom = Prism.languages.xml;
+Prism.languages.rss = Prism.languages.xml;
+
+(function (Prism) {
+
+ var string = /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;
+
+ Prism.languages.css = {
+ 'comment': /\/\*[\s\S]*?\*\//,
+ 'atrule': {
+ pattern: /@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/,
+ inside: {
+ 'rule': /^@[\w-]+/,
+ 'selector-function-argument': {
+ pattern: /(\bselector\s*\((?!\s*\))\s*)(?:[^()]|\((?:[^()]|\([^()]*\))*\))+?(?=\s*\))/,
+ lookbehind: true,
+ alias: 'selector'
+ }
+ // See rest below
+ }
+ },
+ 'url': {
+ pattern: RegExp('url\\((?:' + string.source + '|[^\n\r()]*)\\)', 'i'),
+ greedy: true,
+ inside: {
+ 'function': /^url/i,
+ 'punctuation': /^\(|\)$/
+ }
+ },
+ 'selector': RegExp('[^{}\\s](?:[^{};"\']|' + string.source + ')*?(?=\\s*\\{)'),
+ 'string': {
+ pattern: string,
+ greedy: true
+ },
+ 'property': /[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,
+ 'important': /!important\b/i,
+ 'function': /[-a-z0-9]+(?=\()/i,
+ 'punctuation': /[(){};:,]/
+ };
+
+ Prism.languages.css['atrule'].inside.rest = Prism.languages.css;
+
+ var markup = Prism.languages.markup;
+ if (markup) {
+ markup.tag.addInlined('style', 'css');
+
+ Prism.languages.insertBefore('inside', 'attr-value', {
+ 'style-attr': {
+ pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,
+ inside: {
+ 'attr-name': {
+ pattern: /^\s*style/i,
+ inside: markup.tag.inside
+ },
+ 'punctuation': /^\s*=\s*['"]|['"]\s*$/,
+ 'attr-value': {
+ pattern: /.+/i,
+ inside: Prism.languages.css
+ }
+ },
+ alias: 'language-css'
+ }
+ }, markup.tag);
+ }
+
+}(Prism));
+
+Prism.languages.clike = {
+ 'comment': [
+ {
+ pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,
+ lookbehind: true
+ },
+ {
+ pattern: /(^|[^\\:])\/\/.*/,
+ lookbehind: true,
+ greedy: true
+ }
+ ],
+ 'string': {
+ pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
+ greedy: true
+ },
+ 'class-name': {
+ pattern: /(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,
+ lookbehind: true,
+ inside: {
+ 'punctuation': /[.\\]/
+ }
+ },
+ 'keyword': /\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,
+ 'boolean': /\b(?:true|false)\b/,
+ 'function': /\w+(?=\()/,
+ 'number': /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,
+ 'operator': /[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,
+ 'punctuation': /[{}[\];(),.:]/
+};
+
+Prism.languages.javascript = Prism.languages.extend('clike', {
+ 'class-name': [
+ Prism.languages.clike['class-name'],
+ {
+ pattern: /(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,
+ lookbehind: true
+ }
+ ],
+ 'keyword': [
+ {
+ pattern: /((?:^|})\s*)(?:catch|finally)\b/,
+ lookbehind: true
+ },
+ {
+ pattern: /(^|[^.]|\.\.\.\s*)\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|(?:get|set)(?=\s*[\[$\w\xA0-\uFFFF])|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,
+ lookbehind: true
+ },
+ ],
+ 'number': /\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,
+ // Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)
+ 'function': /#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,
+ 'operator': /--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/
+});
+
+Prism.languages.javascript['class-name'][0].pattern = /(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/;
+
+Prism.languages.insertBefore('javascript', 'keyword', {
+ 'regex': {
+ pattern: /((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,
+ lookbehind: true,
+ greedy: true
+ },
+ // This must be declared before keyword because we use "function" inside the look-forward
+ 'function-variable': {
+ pattern: /#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,
+ alias: 'function'
+ },
+ 'parameter': [
+ {
+ pattern: /(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,
+ lookbehind: true,
+ inside: Prism.languages.javascript
+ },
+ {
+ pattern: /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,
+ inside: Prism.languages.javascript
+ },
+ {
+ pattern: /(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,
+ lookbehind: true,
+ inside: Prism.languages.javascript
+ },
+ {
+ pattern: /((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,
+ lookbehind: true,
+ inside: Prism.languages.javascript
+ }
+ ],
+ 'constant': /\b[A-Z](?:[A-Z_]|\dx?)*\b/
+});
+
+Prism.languages.insertBefore('javascript', 'string', {
+ 'template-string': {
+ pattern: /`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,
+ greedy: true,
+ inside: {
+ 'template-punctuation': {
+ pattern: /^`|`$/,
+ alias: 'string'
+ },
+ 'interpolation': {
+ pattern: /((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,
+ lookbehind: true,
+ inside: {
+ 'interpolation-punctuation': {
+ pattern: /^\${|}$/,
+ alias: 'punctuation'
+ },
+ rest: Prism.languages.javascript
+ }
+ },
+ 'string': /[\s\S]+/
+ }
+ }
+});
+
+if (Prism.languages.markup) {
+ Prism.languages.markup.tag.addInlined('script', 'javascript');
+}
+
+Prism.languages.js = Prism.languages.javascript;
+
+Prism.languages.python = {
+ 'comment': {
+ pattern: /(^|[^\\])#.*/,
+ lookbehind: true
+ },
+ 'string-interpolation': {
+ pattern: /(?:f|rf|fr)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,
+ greedy: true,
+ inside: {
+ 'interpolation': {
+ // "{" <expression> <optional "!s", "!r", or "!a"> <optional ":" format specifier> "}"
+ pattern: /((?:^|[^{])(?:{{)*){(?!{)(?:[^{}]|{(?!{)(?:[^{}]|{(?!{)(?:[^{}])+})+})+}/,
+ lookbehind: true,
+ inside: {
+ 'format-spec': {
+ pattern: /(:)[^:(){}]+(?=}$)/,
+ lookbehind: true
+ },
+ 'conversion-option': {
+ pattern: /![sra](?=[:}]$)/,
+ alias: 'punctuation'
+ },
+ rest: null
+ }
+ },
+ 'string': /[\s\S]+/
+ }
+ },
+ 'triple-quoted-string': {
+ pattern: /(?:[rub]|rb|br)?("""|''')[\s\S]*?\1/i,
+ greedy: true,
+ alias: 'string'
+ },
+ 'string': {
+ pattern: /(?:[rub]|rb|br)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,
+ greedy: true
+ },
+ 'function': {
+ pattern: /((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,
+ lookbehind: true
+ },
+ 'class-name': {
+ pattern: /(\bclass\s+)\w+/i,
+ lookbehind: true
+ },
+ 'decorator': {
+ pattern: /(^\s*)@\w+(?:\.\w+)*/im,
+ lookbehind: true,
+ alias: ['annotation', 'punctuation'],
+ inside: {
+ 'punctuation': /\./
+ }
+ },
+ 'keyword': /\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,
+ 'builtin': /\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,
+ 'boolean': /\b(?:True|False|None)\b/,
+ 'number': /(?:\b(?=\d)|\B(?=\.))(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,
+ 'operator': /[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,
+ 'punctuation': /[{}[\];(),.:]/
+};
+
+Prism.languages.python['string-interpolation'].inside['interpolation'].inside.rest = Prism.languages.python;
+
+Prism.languages.py = Prism.languages.python;
+
+Prism.languages['visual-basic'] = {
+ 'comment': {
+ pattern: /(?:['‘’]|REM\b)(?:[^\r\n_]|_(?:\r\n?|\n)?)*/i,
+ inside: {
+ 'keyword': /^REM/i
+ }
+ },
+ 'directive': {
+ pattern: /#(?:Const|Else|ElseIf|End|ExternalChecksum|ExternalSource|If|Region)(?:[^\S\r\n]_[^\S\r\n]*(?:\r\n?|\n)|.)+/i,
+ alias: 'comment',
+ greedy: true
+ },
+ 'string': {
+ pattern: /\$?["“”](?:["“”]{2}|[^"“”])*["“”]C?/i,
+ greedy: true
+ },
+ 'date': {
+ pattern: /#[^\S\r\n]*(?:\d+([/-])\d+\1\d+(?:[^\S\r\n]+(?:\d+[^\S\r\n]*(?:AM|PM)|\d+:\d+(?::\d+)?(?:[^\S\r\n]*(?:AM|PM))?))?|(?:\d+[^\S\r\n]*(?:AM|PM)|\d+:\d+(?::\d+)?(?:[^\S\r\n]*(?:AM|PM))?))[^\S\r\n]*#/i,
+ alias: 'builtin'
+ },
+ 'number': /(?:(?:\b\d+(?:\.\d+)?|\.\d+)(?:E[+-]?\d+)?|&[HO][\dA-F]+)(?:U?[ILS]|[FRD])?/i,
+ 'boolean': /\b(?:True|False|Nothing)\b/i,
+ 'keyword': /\b(?:AddHandler|AddressOf|Alias|And(?:Also)?|As|Boolean|ByRef|Byte|ByVal|Call|Case|Catch|C(?:Bool|Byte|Char|Date|Dbl|Dec|Int|Lng|Obj|SByte|Short|Sng|Str|Type|UInt|ULng|UShort)|Char|Class|Const|Continue|Currency|Date|Decimal|Declare|Default|Delegate|Dim|DirectCast|Do|Double|Each|Else(?:If)?|End(?:If)?|Enum|Erase|Error|Event|Exit|Finally|For|Friend|Function|Get(?:Type|XMLNamespace)?|Global|GoSub|GoTo|Handles|If|Implements|Imports|In|Inherits|Integer|Interface|Is|IsNot|Let|Lib|Like|Long|Loop|Me|Mod|Module|Must(?:Inherit|Override)|My(?:Base|Class)|Namespace|Narrowing|New|Next|Not(?:Inheritable|Overridable)?|Object|Of|On|Operator|Option(?:al)?|Or(?:Else)?|Out|Overloads|Overridable|Overrides|ParamArray|Partial|Private|Property|Protected|Public|RaiseEvent|ReadOnly|ReDim|RemoveHandler|Resume|Return|SByte|Select|Set|Shadows|Shared|short|Single|Static|Step|Stop|String|Structure|Sub|SyncLock|Then|Throw|To|Try|TryCast|Type|TypeOf|U(?:Integer|Long|Short)|Using|Variant|Wend|When|While|Widening|With(?:Events)?|WriteOnly|Xor)\b/i,
+ 'operator': [
+ /[+\-*/\\^<=>&#@$%!]/,
+ {
+ pattern: /([^\S\r\n])_(?=[^\S\r\n]*[\r\n])/,
+ lookbehind: true
+ }
+ ],
+ 'punctuation': /[{}().,:?]/
+};
+
+Prism.languages.vb = Prism.languages['visual-basic'];
+
+(function () {
+
+ if (typeof self === 'undefined' || !self.Prism || !self.document) {
+ return;
+ }
+
+ /**
+ * Plugin name which is used as a class name for <pre> which is activating the plugin
+ * @type {String}
+ */
+ var PLUGIN_NAME = 'line-numbers';
+
+ /**
+ * Regular expression used for determining line breaks
+ * @type {RegExp}
+ */
+ var NEW_LINE_EXP = /\n(?!$)/g;
+
+ /**
+ * Resizes line numbers spans according to height of line of code
+ * @param {Element} element <pre> element
+ */
+ var _resizeElement = function (element) {
+ var codeStyles = getStyles(element);
+ var whiteSpace = codeStyles['white-space'];
+
+ if (whiteSpace === 'pre-wrap' || whiteSpace === 'pre-line') {
+ var codeElement = element.querySelector('code');
+ var lineNumbersWrapper = element.querySelector('.line-numbers-rows');
+ if (!codeElement || !lineNumbersWrapper) {
+ return;
+ }
+ var lineNumberSizer = element.querySelector('.line-numbers-sizer');
+ var codeLines = codeElement.textContent.split(NEW_LINE_EXP);
+
+ if (!lineNumberSizer) {
+ lineNumberSizer = document.createElement('span');
+ lineNumberSizer.className = 'line-numbers-sizer';
+
+ codeElement.appendChild(lineNumberSizer);
+ }
+
+ lineNumberSizer.style.display = 'block';
+
+ codeLines.forEach(function (line, lineNumber) {
+ lineNumberSizer.textContent = line || '\n';
+ var lineSize = lineNumberSizer.getBoundingClientRect().height;
+ lineNumbersWrapper.children[lineNumber].style.height = lineSize + 'px';
+ });
+
+ lineNumberSizer.textContent = '';
+ lineNumberSizer.style.display = 'none';
+ }
+ };
+
+ /**
+ * Returns style declarations for the element
+ * @param {Element} element
+ */
+ var getStyles = function (element) {
+ if (!element) {
+ return null;
+ }
+
+ return window.getComputedStyle ? getComputedStyle(element) : (element.currentStyle || null);
+ };
+
+ window.addEventListener('resize', function () {
+ Array.prototype.forEach.call(document.querySelectorAll('pre.' + PLUGIN_NAME), _resizeElement);
+ });
+
+ Prism.hooks.add('complete', function (env) {
+ if (!env.code) {
+ return;
+ }
+
+ var code = env.element;
+ var pre = code.parentNode;
+
+ // works only for <code> wrapped inside <pre> (not inline)
+ if (!pre || !/pre/i.test(pre.nodeName)) {
+ return;
+ }
+
+ // Abort if line numbers already exists
+ if (code.querySelector('.line-numbers-rows')) {
+ return;
+ }
+
+ var addLineNumbers = false;
+ var lineNumbersRegex = /(?:^|\s)line-numbers(?:\s|$)/;
+
+ for (var element = code; element; element = element.parentNode) {
+ if (lineNumbersRegex.test(element.className)) {
+ addLineNumbers = true;
+ break;
+ }
+ }
+
+ // only add line numbers if <code> or one of its ancestors has the `line-numbers` class
+ if (!addLineNumbers) {
+ return;
+ }
+
+ // Remove the class 'line-numbers' from the <code>
+ code.className = code.className.replace(lineNumbersRegex, ' ');
+ // Add the class 'line-numbers' to the <pre>
+ if (!lineNumbersRegex.test(pre.className)) {
+ pre.className += ' line-numbers';
+ }
+
+ var match = env.code.match(NEW_LINE_EXP);
+ var linesNum = match ? match.length + 1 : 1;
+ var lineNumbersWrapper;
+
+ var lines = new Array(linesNum + 1).join('<span></span>');
+
+ lineNumbersWrapper = document.createElement('span');
+ lineNumbersWrapper.setAttribute('aria-hidden', 'true');
+ lineNumbersWrapper.className = 'line-numbers-rows';
+ lineNumbersWrapper.innerHTML = lines;
+
+ if (pre.hasAttribute('data-start')) {
+ pre.style.counterReset = 'linenumber ' + (parseInt(pre.getAttribute('data-start'), 10) - 1);
+ }
+
+ env.element.appendChild(lineNumbersWrapper);
+
+ _resizeElement(pre);
+
+ Prism.hooks.run('line-numbers', env);
+ });
+
+ Prism.hooks.add('line-numbers', function (env) {
+ env.plugins = env.plugins || {};
+ env.plugins.lineNumbers = true;
+ });
+
+ /**
+ * Global exports
+ */
+ Prism.plugins.lineNumbers = {
+ /**
+ * Returns the node of the given line number in the given element.
+ * @param {Element} element A `<pre>` element with line numbers.
+ * @param {Number} number
+ * @returns {Element | undefined}
+ */
+ getLine: function (element, number) {
+ if (element.tagName !== 'PRE' || !element.classList.contains(PLUGIN_NAME)) {
+ return;
+ }
+
+ var lineNumberRows = element.querySelector('.line-numbers-rows');
+ var lineNumberStart = parseInt(element.getAttribute('data-start'), 10) || 1;
+ var lineNumberEnd = lineNumberStart + (lineNumberRows.children.length - 1);
+
+ if (number < lineNumberStart) {
+ number = lineNumberStart;
+ }
+ if (number > lineNumberEnd) {
+ number = lineNumberEnd;
+ }
+
+ var lineIndex = number - lineNumberStart;
+
+ return lineNumberRows.children[lineIndex];
+ },
+ /**
+ * Resizes the line numbers of the given element.
+ *
+ * This function will not add line numbers. It will only resize existing ones.
+ * @param {Element} element A `<pre>` element with line numbers.
+ * @returns {void}
+ */
+ resize: function (element) {
+ _resizeElement(element);
+ }
+ };
+
+}());
+
+(function() {
+
+var assign = Object.assign || function (obj1, obj2) {
+ for (var name in obj2) {
+ if (obj2.hasOwnProperty(name))
+ obj1[name] = obj2[name];
+ }
+ return obj1;
+}
+
+function NormalizeWhitespace(defaults) {
+ this.defaults = assign({}, defaults);
+}
+
+function toCamelCase(value) {
+ return value.replace(/-(\w)/g, function(match, firstChar) {
+ return firstChar.toUpperCase();
+ });
+}
+
+function tabLen(str) {
+ var res = 0;
+ for (var i = 0; i < str.length; ++i) {
+ if (str.charCodeAt(i) == '\t'.charCodeAt(0))
+ res += 3;
+ }
+ return str.length + res;
+}
+
+NormalizeWhitespace.prototype = {
+ setDefaults: function (defaults) {
+ this.defaults = assign(this.defaults, defaults);
+ },
+ normalize: function (input, settings) {
+ settings = assign(this.defaults, settings);
+
+ for (var name in settings) {
+ var methodName = toCamelCase(name);
+ if (name !== "normalize" && methodName !== 'setDefaults' &&
+ settings[name] && this[methodName]) {
+ input = this[methodName].call(this, input, settings[name]);
+ }
+ }
+
+ return input;
+ },
+
+ /*
+ * Normalization methods
+ */
+ leftTrim: function (input) {
+ return input.replace(/^\s+/, '');
+ },
+ rightTrim: function (input) {
+ return input.replace(/\s+$/, '');
+ },
+ tabsToSpaces: function (input, spaces) {
+ spaces = spaces|0 || 4;
+ return input.replace(/\t/g, new Array(++spaces).join(' '));
+ },
+ spacesToTabs: function (input, spaces) {
+ spaces = spaces|0 || 4;
+ return input.replace(RegExp(' {' + spaces + '}', 'g'), '\t');
+ },
+ removeTrailing: function (input) {
+ return input.replace(/\s*?$/gm, '');
+ },
+ // Support for deprecated plugin remove-initial-line-feed
+ removeInitialLineFeed: function (input) {
+ return input.replace(/^(?:\r?\n|\r)/, '');
+ },
+ removeIndent: function (input) {
+ var indents = input.match(/^[^\S\n\r]*(?=\S)/gm);
+
+ if (!indents || !indents[0].length)
+ return input;
+
+ indents.sort(function(a, b){return a.length - b.length; });
+
+ if (!indents[0].length)
+ return input;
+
+ return input.replace(RegExp('^' + indents[0], 'gm'), '');
+ },
+ indent: function (input, tabs) {
+ return input.replace(/^[^\S\n\r]*(?=\S)/gm, new Array(++tabs).join('\t') + '$&');
+ },
+ breakLines: function (input, characters) {
+ characters = (characters === true) ? 80 : characters|0 || 80;
+
+ var lines = input.split('\n');
+ for (var i = 0; i < lines.length; ++i) {
+ if (tabLen(lines[i]) <= characters)
+ continue;
+
+ var line = lines[i].split(/(\s+)/g),
+ len = 0;
+
+ for (var j = 0; j < line.length; ++j) {
+ var tl = tabLen(line[j]);
+ len += tl;
+ if (len > characters) {
+ line[j] = '\n' + line[j];
+ len = tl;
+ }
+ }
+ lines[i] = line.join('');
+ }
+ return lines.join('\n');
+ }
+};
+
+// Support node modules
+if (typeof module !== 'undefined' && module.exports) {
+ module.exports = NormalizeWhitespace;
+}
+
+// Exit if prism is not loaded
+if (typeof Prism === 'undefined') {
+ return;
+}
+
+Prism.plugins.NormalizeWhitespace = new NormalizeWhitespace({
+ 'remove-trailing': true,
+ 'remove-indent': true,
+ 'left-trim': true,
+ 'right-trim': true,
+ /*'break-lines': 80,
+ 'indent': 2,*/
+ 'remove-initial-line-feed': true,
+ /*'tabs-to-spaces': 4,
+ 'spaces-to-tabs': 4*/
+});
+
+Prism.hooks.add('before-sanity-check', function (env) {
+ var Normalizer = Prism.plugins.NormalizeWhitespace;
+
+ // Check settings
+ if (env.settings && env.settings['whitespace-normalization'] === false) {
+ return;
+ }
+
+ // Simple mode if there is no env.element
+ if ((!env.element || !env.element.parentNode) && env.code) {
+ env.code = Normalizer.normalize(env.code, env.settings);
+ return;
+ }
+
+ // Normal mode
+ var pre = env.element.parentNode;
+ var clsReg = /(?:^|\s)no-whitespace-normalization(?:\s|$)/;
+ if (!env.code || !pre || pre.nodeName.toLowerCase() !== 'pre' ||
+ clsReg.test(pre.className) || clsReg.test(env.element.className))
+ return;
+
+ var children = pre.childNodes,
+ before = '',
+ after = '',
+ codeFound = false;
+
+ // Move surrounding whitespace from the <pre> tag into the <code> tag
+ for (var i = 0; i < children.length; ++i) {
+ var node = children[i];
+
+ if (node == env.element) {
+ codeFound = true;
+ } else if (node.nodeName === "#text") {
+ if (codeFound) {
+ after += node.nodeValue;
+ } else {
+ before += node.nodeValue;
+ }
+
+ pre.removeChild(node);
+ --i;
+ }
+ }
+
+ if (!env.element.children.length || !Prism.plugins.KeepMarkup) {
+ env.code = before + env.code + after;
+ env.code = Normalizer.normalize(env.code, env.settings);
+ } else {
+ // Preserve markup for keep-markup plugin
+ var html = before + env.element.innerHTML + after;
+ env.element.innerHTML = Normalizer.normalize(html, env.settings);
+ env.code = env.element.textContent;
+ }
+});
+
+}());
+
diff --git a/helpcontent2/help3xsl/xap_templ_query.xsl b/helpcontent2/help3xsl/xap_templ_query.xsl
new file mode 100644
index 000000000..a606d2fc2
--- /dev/null
+++ b/helpcontent2/help3xsl/xap_templ_query.xsl
@@ -0,0 +1,295 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+* This file is part of the LibreOffice project.
+*
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<!--
+Stylesheet to create the localized xapian template.
+Based on the query template from xapian
+Usage:
+xsltproc xap_template_query.xsl <file.xhp>
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <xsl:param name="lang"/>
+ <xsl:param name="productname"/>
+ <xsl:param name="productversion"/>
+ <xsl:output indent="yes" method="text"/>
+ <xsl:variable name="target" select="concat('/',$productversion,'/')"/>
+ <!-- Strings for the help UI page -->
+ <xsl:variable name ="ui_contents"><xsl:apply-templates select="//variable[@id='contents']"/></xsl:variable>
+ <xsl:variable name ="ui_index"><xsl:apply-templates select="//variable[@id='index']"/></xsl:variable>
+ <xsl:variable name ="ui_pholderall"><xsl:apply-templates select="//variable[@id='pholderall']"/></xsl:variable>
+ <xsl:variable name ="ui_pholderchosen"><xsl:apply-templates select="//variable[@id='pholderchosen']"/></xsl:variable>
+ <xsl:variable name ="ui_module"><xsl:apply-templates select="//variable[@id='module']"/></xsl:variable>
+ <xsl:variable name ="ui_language"><xsl:apply-templates select="//variable[@id='language']"/></xsl:variable>
+ <xsl:variable name ="ui_donate"><xsl:apply-templates select="//variable[@id='donate']"/></xsl:variable>
+ <xsl:variable name ="ui_logo"><xsl:apply-templates select="//variable[@id='LibreOfficeHelp']"/></xsl:variable>
+ <xsl:variable name ="ui_selectmodule"><xsl:apply-templates select="//variable[@id='selectmodule']"/></xsl:variable>
+ <xsl:variable name ="ui_selectlang"><xsl:apply-templates select="//variable[@id='selectlanguage']"/></xsl:variable>
+ <xsl:variable name ="ui_search"><xsl:apply-templates select="//variable[@id='searchhelpcontents']"/></xsl:variable>
+
+ <xsl:variable name="brand3" select="'%PRODUCTNAME'"/>
+ <xsl:variable name="brand4" select="'%PRODUCTVERSION'"/>
+
+
+<xsl:template match="/">
+<![CDATA[$httpheader{Content-Type,text/html; charset=utf-8}<!DOCTYPE html><html lang="]]><xsl:value-of select="$lang"/><![CDATA[">
+<base href="]]><xsl:value-of select="$target"/><![CDATA["/>
+$set{flag_spelling,$ne{$cgi{SPELL},0}}
+$set{stemmer,$if{$cgi{STEMMER},$cgi{STEMMER},none}}
+$set{flag_spelling_correction,true}
+$set{thousand,$.}$set{decimal,.}
+$setmap{prefix,,$split{ S B F},title,S,author,A,topic,B}
+${
+$def{PREV,
+$if{$ne{$topdoc,0},<input type=image name="&lt;" alt="&lt;"
+src="/images/xapian-omega/prev.png" height=30 width=30>,
+<img alt="" src="/images/xapian-omega/prevoff.png" height=30 width=30>}
+}
+
+$def{NEXT,
+$if{$ne{$last,$msize},<input type=image name="&gt;" alt="&gt;"
+src="/images/xapian-omega/next.png" height=30 width=30>,
+<img alt="" src="/images/xapian-omega/nextoff.png" height=30 width=30>}
+}
+
+$def{P,<input type=image name="$1" value="$1" src="/images/xapian-omega/page-$2.png" $opt{a} alt="$1">}
+$def{PAGE,$if{$gt{$1,9},$if{$gt{$1,99},$P{$1,$div{$1,100}}}$P{$1,$mod{$div{$1,10},10}}}$P{$1,$mod{$1,10}}}
+
+$def{S,<img src="/images/xapian-omega/page-$2s.png" $opt{a} alt=$1>}
+$def{SPAGE,$if{$gt{$1,9},$if{$gt{$1,99},$S{$1,$div{$1,100}}}$S{$1,$mod{$div{$1,10},10}}}$S{$1,$mod{$1,10}}}
+}
+
+$def{PREV,$if{$ne{$topdoc,0},<input type=submit name="&lt;" value="]]><xsl:apply-templates select="//variable[@id='xap_previous']"/><![CDATA[">}}
+
+$def{PAGE,<input type=submit name="[" value="$1">}
+
+$def{SPAGE,<input type=submit name="[" value="$1" disabled=disabled>}
+
+ $def{NEXT,$if{$ne{$last,$msize},<input type=submit name="&gt;" value="]]><xsl:apply-templates select="//variable[@id='xap_next']"/><![CDATA[">}}
+
+<head>
+<title>$if{$query,Omega Search: $html{$query},Omega Search}</title>
+<!--$if{$opt{topterms},$include{inc/toptermsjs}}-->
+<link rel="shortcut icon" href="media/navigation/favicon.ico"/>
+<link type="text/css" href="normalize.css" rel="Stylesheet"/>
+<link type="text/css" href="default.css" rel="Stylesheet"/>
+<link type="text/css" href="prism.css" rel="Stylesheet"/>
+<script type="text/javascript" src="polyfills.js"></script>
+<script type="text/javascript" src="languages.js"></script>
+<script type="text/javascript" src="]]><xsl:value-of select="$lang"/><![CDATA[/langnames.js"></script>
+<script type="text/javascript" src="fuzzysort.js"></script>
+<script type="text/javascript" src="prism.js"></script>
+<script type="text/javascript" src="help2.js" defer=""></script>
+<script type="text/javascript" src="a11y-toggle.js" defer=""></script>
+<script type="text/javascript" src="paginathing.js" defer=""></script>
+<script type="text/javascript" src="]]><xsl:value-of select="$lang"/><![CDATA[/bookmarks.js" defer=""></script>
+<script type="text/javascript" src="]]><xsl:value-of select="$lang"/><![CDATA[/contents.js" defer=""></script>
+<script type="text/javascript" src="help.js" defer=""></script>
+<meta name="viewport" content="width=device-width,initial-scale=1"/>
+<style>
+input[type=image] {
+ border: 0px;
+ }
+</style>
+<script type="text/javascript">
+function f2(n) {return (n>9?"":"0")+n;}
+function write_date(time_t) {
+var d=new Date();d.setTime(time_t*1000);
+var D=d.getFullYear()+"-"+f2(d.getMonth()+1)+"-"+f2(d.getDate());
+var T=f2(d.getHours())+":"+f2(d.getMinutes())+":"+f2(d.getSeconds());
+document.write("<span title=\""+D+" "+T+"\">]]><xsl:apply-templates select="//variable[@id='xap_modified']"/><![CDATA[<br><b>"+D+"</b></span>");
+}
+</script>
+</head>
+<body>
+<div id="TopLeftHeader">
+ <header>
+ <div class="logo-container">
+ <a class="logo" href="]]><xsl:value-of select="$lang"/><![CDATA[/text/shared/05/new_help.html">
+ <div class="symbol"></div>
+ <p>]]><xsl:value-of select="$ui_logo"/><![CDATA[</p>
+ </a>
+ </div>
+ </header>
+</div>
+<div class="modules">
+ <button type="button" data-a11y-toggle="modules-nav" id="modules" onclick="setupModules(']]><xsl:value-of select="$lang"/><![CDATA[');">]]><xsl:value-of select="$ui_module"/><![CDATA[
+ </button>
+ <nav id="modules-nav"/><!-- is filled in via setupModules() on demand -->
+</div>
+<aside class="rightside">
+ <input id="accordion-1" name="accordion-menu" type="checkbox"/>
+ <label for="accordion-1">]]><xsl:value-of select="$ui_contents"/><![CDATA[</label>
+ <div id="Contents" class="contents-treeview"></div>
+</aside>
+<aside class="leftside">
+ <div id="Index">
+ <div class="index-label">]]><xsl:value-of select="$ui_index"/><![CDATA[ &#32;&#x1f50e;&#xfe0e;&#32;</div>
+ <div id="Bookmarks">
+ <input id="search-bar" type="text" class="search" placeholder="]]><xsl:value-of select="$ui_pholderchosen"/><![CDATA["/>
+ <nav class="index"></nav>
+ </div>
+ </div>
+</aside>
+<div id="DonationFrame">
+ <div class="donation">
+ <p><a href="https://www.libreoffice.org/donate/?pk_campaign=help" target ="_blank">]]><xsl:value-of select="$ui_donate"/><![CDATA[</a></p>
+ </div>
+</div>
+<div id="SearchFrame">
+ <div class="xapian-omega-search">
+ </div>
+</div>
+<div id="DisplayArea">
+ <form name="P" method="get" action="]]><xsl:value-of select="$lang"/><![CDATA[/search" target="_top">
+<center>
+<input id="omega-autofocus" type=search name=P value="$html{$query}" size=40 autofocus>
+<script>
+if (!("autofocus" in document.createElement("input")))
+ document.getElementById("omega-autofocus").focus();
+</script>
+<input type="submit" class="xapian-omega-search-button" value="&#x1f50d;"/>
+<hr>
+<input type=radio name=DEFAULTOP value=and $if{$eq{$defaultop,and},checked}>]]><xsl:apply-templates select="//variable[@id='xap_match_all']"/><![CDATA[
+<input type=radio name=DEFAULTOP value=or $if{$eq{$defaultop,or},checked}>]]><xsl:apply-templates select="//variable[@id='xap_match_any']"/><![CDATA[
+$if{$opt{topterms},
+ <div title="Suggested terms to add to your query"
+ style="text-align:left;background:#cfc;border:1px solid green;padding:2px;font:11px verdana$. arial$. helvetica$. sans-serif;">
+ $map{$topterms,<span style="white-space:nowrap"><input type=checkbox name=X value="$html{$prettyterm{$_}}" onClick="C(this)">$html{$prettyterm{$_}}</span> }
+ <br><noscript><input type=hidden name=ADD value=1></noscript>
+ </div>
+}
+<br>
+$if{$suggestion,]]><xsl:apply-templates select="//variable[@id='xap_didyoumean']"/><![CDATA[ <a href="$html{$or{$env{SCRIPT_NAME},omega}?P=$url{$suggestion}$if{$ne{$hitsperpage,10},&HITSPERPAGE=$hitsperpage}$if{$cgi{COLLAPSE},&COLLAPSE=$url{$cgi{COLLAPSE}}}$map{$relevants,&R=$_}$if{$cgi{THRESHOLD},&THRESHOLD=$url{$cgi{THRESHOLD}}}$map{$cgilist{B},&B=$url{$_}}&SPELL=0}">$html{$suggestion}</a><br>}
+
+$or{$html{$error},
+$if{$eq{$msize,0},
+$if{$query,]]><xsl:apply-templates select="//variable[@id='xap_no_match']"/><![CDATA[,
+<hr>]]><xsl:apply-templates select="//variable[@id='xap_searching_doc']"/><![CDATA[
+},
+$if{$not{$msizeexact},
+$nice{$add{$topdoc,1}}-$nice{$last} ]]><xsl:apply-templates select="//variable[@id='xap_about']"/><![CDATA[,
+ $if{$and{$eq{$last,$msize},$eq{$topdoc,0}},
+ ]]><xsl:apply-templates select="//variable[@id='xap_allmatches']"/><![CDATA[ ,
+ $nice{$add{$topdoc,1}}$if{$ne{$add{$topdoc,1},$last},-$nice{$last}} ]]><xsl:apply-templates select="//variable[@id='xap_exactly']"/><![CDATA[}
+}
+<hr>
+
+</center>
+$if{$map{$queryterms,$set{U,$unstem{$_}}$set{F_$opt{U},$add{$opt{F_$opt{U}},$freq{$_}}}},$list{$unique{$map{$queryterms,$set{U,$unstem{$_}}$list{$html{$unique{$opt{U}}},<b>,</b>/<b>,</b>}:&nbsp;$nice{$opt{F_$opt{U}}}}},]]><xsl:apply-templates select="//variable[@id='xap_term_frequencies']"/><![CDATA[ ,$. ,}}
+<br><small>]]><xsl:apply-templates select="//variable[@id='xap_searchtimes']"/><![CDATA[</small>
+<table>
+$hitlist{<tr><td valign=top>
+${<img src="/images/xapian-omega/score-$div{$percentage,10}.png" alt="$percentage%" height=16 width=32>}
+<div title="$percentage%" style='float:left;width:60px;height:10px;border:1px solid black;margin-top:4px;'>
+<div style='width:$div{$mul{$percentage,6},10}px; height:10px; background-color: red;'>
+</div></div>
+<div style='float:left;margin-top:2px;font-size:x-small;'>
+$if{$and{$field{modtime},$ne{$field{modtime},-1}},
+<script type="text/javascript">write_date($add{$field{modtime}});</script>
+<noscript>
+<span title="$html{$date{$field{modtime},%Y-%m-%d %H:%M:%S}}">
+]]><xsl:apply-templates select="//variable[@id='xap_modified']"/><![CDATA[<br><b>$html{$date{$field{modtime},%Y-%m-%d}}</b></span>
+</noscript><br>
+}
+$if{$field{language},]]><xsl:apply-templates select="//variable[@id='xap_lang']"/><![CDATA[<b>$html{$field{language}}</b><br>}
+$if{$field{size},<span title="$html{$field{size}} bytes">]]><xsl:apply-templates select="//variable[@id='xap_size']"/><![CDATA[<b>$html{$filesize{$field{size}}}</b></span><br>}
+<div title="]]><xsl:apply-templates select="//variable[@id='xap_relevant']"/><![CDATA[" style="float:left;background-color:#cfc;border:1px solid green;margin-top:2px;">
+<input type=checkbox name=R value=$id$if{$relevant, checked}>
+</div>
+</div>
+</td>
+<td><b><a href="$html{$field{url}}">$html{$or{$field{caption},$field{title},$prettyurl{$field{url}},Untitled}}</a></b><br>
+<small>$snippet{$field{sample}}</small><br>
+<a href="$html{$field{url}}">$html{$prettyurl{$field{url}}}</a><br>
+<small>
+]]><xsl:apply-templates select="//variable[@id='xap_matching']"/><![CDATA[
+<i>$list{$map{$terms,$html{$prettyterm{$_}}},</i>$. <i>,</i> and <i>}</i></small>${for lynx:}<p></td></tr>}
+</table>
+
+<br><center>
+
+${suppress next, prev, and page links if there's only one page}
+$if{$ne{$lastpage,1},
+$set{a,$if{$opt{pagelink_height}, HEIGHT=$opt{pagelink_height}}$if{$opt{pagelink_width}, WIDTH=$opt{pagelink_width}}}
+
+${1-W ... X-(this)-Y ...}
+$set{w,$min{3,$add{$thispage,-1}}}
+$set{x,$max{$add{$opt{w},1},$add{$thispage,-3}}}
+$set{y,$min{$lastpage,$add{$thispage,8}}}
+$PREV
+$map{$range{1,$opt{w}},$PAGE{$_}}
+$if{$ne{$add{$opt{w},1},$opt{x}},...}
+$map{$range{$opt{x},$add{$thispage,-1}},$PAGE{$_}}
+$SPAGE{$thispage}
+$map{$range{$add{$thispage,1},$opt{y}},$PAGE{$_}}
+$if{$ne{$opt{y},$lastpage},...}
+$NEXT
+}
+}}
+</center><br>
+$if{$ne{$topdoc,0},<input type=hidden name=TOPDOC value=$topdoc>}
+$if{$ne{$hitsperpage,10},<input type=hidden name=HITSPERPAGE value=$hitsperpage>}
+$if{$cgi{COLLAPSE},<input type=hidden name=COLLAPSE value="$html{$cgi{COLLAPSE}}">}
+$if{$queryterms,<input type=hidden name=xP value="$html{$queryterms}">}
+<input type=hidden name=xFILTERS value="$html{$filters}">
+$list{$relevants,<input type=hidden name=R value=",.,">}
+$if{$cgi{THRESHOLD},<input type=hidden name=THRESHOLD value="$html{$cgi{THRESHOLD}}">}
+${Preserve any B filters used - this needs modifying if you modify this template
+ to have B on radio buttons, SELECT, etc}
+$map{$cgilist{B},<input type=hidden name=B value="$html{$_}">}
+</form>
+<hr><div align=right><i><small><a href="https://xapian.org/">$html{$version}</a></small></i></div>
+ <footer>
+ <p><a href="https://www.libreoffice.org/imprint" target="_blank">Impressum (Legal Info)</a> | <a href="https://www.libreoffice.org/privacy" target="_blank">Privacy Policy</a> | <a href="https://www.documentfoundation.org/statutes.pdf" target="_blank">Statutes (non-binding English translation)</a> - <a href="https://www.documentfoundation.org/satzung.pdf" target="_blank">Satzung (binding German version)</a> | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the <a href="https://www.libreoffice.org/download/license/" target="_blank">Mozilla Public License v2.0</a>. “LibreOffice” and “The Document Foundation” are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our <a href="https://wiki.documentfoundation.org/TradeMark_Policy" target="_blank">trademark policy</a>. LibreOffice was based on OpenOffice.org.</p>
+ </footer>
+</body>
+</html>
+$log{query.log}
+</div>
+]]>
+</xsl:template>
+
+<xsl:template match="text()">
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string"><xsl:value-of select="."/></xsl:with-param>
+ </xsl:call-template>
+</xsl:template>
+
+<!-- Branding -->
+<xsl:template name="brand" >
+ <xsl:param name="string"/>
+ <xsl:choose>
+ <xsl:when test="contains($string,$brand3)">
+ <xsl:variable name="newstr">
+ <xsl:value-of select="substring-before($string,$brand3)"/>
+ <xsl:value-of select="$productname"/>
+ <xsl:value-of select="substring-after($string,$brand3)"/>
+ </xsl:variable>
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string" select="$newstr"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="contains($string,$brand4)">
+ <xsl:variable name="newstr">
+ <xsl:value-of select="substring-before($string,$brand4)"/>
+ <xsl:value-of select="$productversion"/>
+ <xsl:value-of select="substring-after($string,$brand4)"/>
+ </xsl:variable>
+ <xsl:call-template name="brand">
+ <xsl:with-param name="string" select="$newstr"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:value-of select="$string"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+</xsl:stylesheet>