diff --git a/src/main/java/nl/imvertor/OfficeCompiler/OfficeCompiler.java b/src/main/java/nl/imvertor/OfficeCompiler/OfficeCompiler.java index 7ff35188b..ecc2ec28e 100644 --- a/src/main/java/nl/imvertor/OfficeCompiler/OfficeCompiler.java +++ b/src/main/java/nl/imvertor/OfficeCompiler/OfficeCompiler.java @@ -25,7 +25,6 @@ import java.util.Iterator; import java.util.Vector; -import org.apache.commons.exec.CommandLine; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.eclipse.jgit.transport.PushResult; @@ -37,10 +36,12 @@ import nl.imvertor.common.file.AnyFile; import nl.imvertor.common.file.AnyFolder; import nl.imvertor.common.file.FtpFolder; +import nl.imvertor.common.file.WordFile; +import nl.imvertor.common.file.XmlFile; import nl.imvertor.common.file.ZipFile; import nl.imvertor.common.git.ResourcePusher; -import nl.imvertor.common.helper.OsExecutor; -import nl.imvertor.common.helper.OsExecutor.OsExecutorResultHandler; +import nl.imvertor.common.xsl.extensions.ImvertorCalculateHashlabel; +import nl.imvertor.common.xsl.extensions.expath.ImvertorExpathWriteBinary; public class OfficeCompiler extends Step { @@ -49,6 +50,9 @@ public class OfficeCompiler extends Step { public static final String STEP_NAME = "OfficeCompiler"; public static final String VC_IDENTIFIER = "$Id: OfficeCompiler.java 7457 2016-03-05 08:43:43Z arjan $"; + private AnyFolder workFolder; + private AnyFolder moduleFolder; + public boolean run() throws Exception{ // set up the configuration for this step @@ -79,7 +83,9 @@ public void generateOfficeReport() throws Exception { if (op.equals("html")) { runner.info(logger,"Creating documentation"); Transformer transformer = new Transformer(); - + transformer.setExtensionFunction(new ImvertorCalculateHashlabel()); + transformer.setExtensionFunction(new ImvertorExpathWriteBinary()); + boolean succeeds = true; // append codelists and reference lists to imvertor file when referenced and when required. @@ -93,10 +99,12 @@ public void generateOfficeReport() throws Exception { succeeds = succeeds ? transformer.transformStep("properties/WORK_LISTS_FILE","properties/WORK_MODELDOC_FILE", "properties/IMVERTOR_METAMODEL_" + dr + "_MODELDOC_XSLPATH") : false; */ int i = 1; + String lastModeldocFile = ""; while (true) { String xslname = "IMVERTOR_METAMODEL_" + dr + "_MODELDOC_XSLPATH" + ((i == 1) ? "" : ("_" + i)); String outname = "WORK_MODELDOC_FILE" + ((i == 1) ? "" : ("_" + i)); if (configurator.getParm("properties", xslname, false) != null) { + lastModeldocFile = configurator.getXParm("properties/" + outname); // onthoud welk file als laatste in de reeks is gegenereerd succeeds = succeeds ? transformer.transformStep("system/cur-imvertor-filepath","properties/" + outname, "properties/" + xslname, "system/cur-imvertor-filepath") : false ; i += 1; } else if (i == 0) { @@ -107,13 +115,14 @@ public void generateOfficeReport() throws Exception { break; } - // variants may be "office" or "respec" Vector vr = Configurator.split(configurator.getXParm("cli/createofficevariant"),"\\s+"); - if (vr.contains("msword") || vr.contains("respec")) { + if (vr.contains("msword") || vr.contains("respec") || vr.contains("documentor")) { String template = configurator.getXParm("cli/officename"); // e.g. resolved [project-name]-[application-name]-[phase]-[release] String fn = configurator.mergeParms(template); + configurator.setXParm("system/officename-resolved", fn); // resolved, dus bijv. CM-Testmodel-1-20231114 + if (vr.contains("msword")) { succeeds = succeeds ? transformer.transformStep("system/cur-imvertor-filepath","properties/WORK_MSWORD_FILE", "properties/IMVERTOR_METAMODEL_" + dr + "_MODELDOC_MSWORD_XSLPATH") : false; if (succeeds) processDoc(fn,"msword.html","appinfo/msword-documentation-filename","properties/WORK_MSWORD_FILE","none"); @@ -124,45 +133,109 @@ public void generateOfficeReport() throws Exception { if (mswordFolder.isDirectory()) mswordFolder.copy(new AnyFolder(configurator.getXParm("system/work-cat-folder-path") + "/msword")); } - } - if (vr.contains("respec")) { - if (configurator.isTrue("cli","fullrespec", false)) { - // process complete report - transformer.setXslParm("catalog-only", "false"); - succeeds = succeeds ? transformer.transformStep("system/cur-imvertor-filepath","properties/WORK_RESPEC_FILE", "properties/IMVERTOR_METAMODEL_" + dr + "_MODELDOC_RESPEC_XSLPATH") : false; - if (succeeds) processDoc(fn,"respec.full.html","appinfo/full-respec-documentation-filename","properties/WORK_RESPEC_FILE","none"); - } - // process catalog only, save as HTML - transformer.setXslParm("catalog-only", "true"); - succeeds = succeeds ? transformer.transformStep("system/cur-imvertor-filepath","properties/WORK_RESPEC_FILE", "properties/IMVERTOR_METAMODEL_" + dr + "_MODELDOC_RESPEC_XSLPATH") : false; - if (succeeds) processDoc(fn,"respec.html","appinfo/respec-documentation-filename","properties/WORK_RESPEC_FILE",configurator.getXParm("cli/passoffice",false)); + }//msword + if (vr.contains("respec") || vr.contains("documentor")) { + // process catalog only, save as XHTML succeeds = succeeds ? transformer.transformStep("system/cur-imvertor-filepath","properties/WORK_RESPEC_FILE", "properties/IMVERTOR_MODELDOC_RESPEC_XSLPATH") : false; - if (succeeds) processDoc(fn,"respec.catalog.xhtml","appinfo/respec-documentation-filename","properties/WORK_RESPEC_FILE","none"); + if (succeeds) processDoc(fn,"respec.catalog.xhtml","appinfo/catalog-documentation-filename","properties/WORK_RESPEC_FILE","none"); - // De laatste output is de XHTML catalogus; die staat centraal in documentor. - /* // als documentor info beschikbaar is, dan uitpakken en omzetten naar xhtml met Pandoc - AnyFile docFile = new AnyFile(configurator.getXParm("cli/modeldocfile",false)); - if (docFile != null) { - boolean isFolder = docFile.isDirectory(); + String mdf = configurator.getXParm("cli/documentorfile",false); + + if (mdf == null && vr.contains("documentor")) { + runner.warn(logger, "Documentor processing requested but no modeldoc folder passed"); + succeeds = false; + } + + if (succeeds && vr.contains("documentor")) { + + // Er is documentor input in de vorm van modeldocs meegeleverd. + + // Maak de workfolder en de module folder aan + workFolder = new AnyFolder(configurator.getWorkFolder("documentor")); + if (workFolder.isDirectory()) workFolder.deleteDirectory(); + workFolder.mkdir(); + configurator.setXParm("documentor/modeldoc-workfolder",workFolder.getCanonicalPath()); + + moduleFolder = new AnyFolder(workFolder,"module"); + if (moduleFolder.isDirectory()) moduleFolder.deleteDirectory(); + moduleFolder.mkdir(); + configurator.setXParm("documentor/modeldoc-modulefolder",moduleFolder.getCanonicalPath()); + + // check het type modeldoc. In development: folder, in productie: zipfile + AnyFile docFile = new AnyFile(mdf); boolean isZip = docFile.getExtension().equals("zip"); if (isZip) { + runner.debug(logger,"CHAIN","Extracting documentor files"); // alles uitpakken naar de workfolder - AnyFolder docFolder = new AnyFolder(configurator.getWorkFolder("modeldoc")); ZipFile zipFile = new ZipFile(docFile); - zipFile.decompress(docFolder); - // ga door deze files heen en zet ze om naar XHTML - Iterator it = docFolder.listFilesToVector(false).iterator(); - while (it.hasNext()) { - AnyFile f = new AnyFile(it.next()); - if (f.getExtension().equals("docx")) - succeeds = succeeds ? transformDocx(f) : false ; - } + zipFile.decompress(workFolder); + } else { + runner.debug(logger,"CHAIN","Copying documentor files"); + // alles kopieren naar de workfolder + (new AnyFolder(docFile)).copy(workFolder); + } + + // maak een kopie van alle *relevante* files in de workfolder en verzamel deze in de modulefolder. + String modelName = configurator.getXParm("appinfo/original-application-name"); + succeeds = succeeds ? copyFilesToModulefolder(workFolder + "/modeldoc/" + modelName, modelName, true, true) : false; + succeeds = succeeds ? copyFilesToModulefolder(workFolder + "/sections", modelName, true, false) : false; + + // de files zijn uitgelezen en omgezet naar XHTML + // nu de bestanden integreren, start bij het masterdoc, als dat er is -- masterdoc wordt bepaald bij het scannen van de files.. + String masterdocPath = configurator.getXParm("documentor/masterdoc-path",false); + if (masterdocPath == null) { + runner.warn(logger, "Documentor processing requested but no modeldoc file \"" + modelName + "/" + modelName + ".docx\" found"); + succeeds = false; + } + // kopieer het masterdoc naar de imvertor workfolder + if (succeeds) { + (new AnyFile(masterdocPath)).copyFile(configurator.getXParm("properties/IMVERTOR_DOCUMENTOR_CORESCANNER_FILE")); + succeeds = succeeds ? transformer.transformStep("system/cur-imvertor-filepath","properties/IMVERTOR_DOCUMENTOR_CORESCANNER_FILE", "properties/IMVERTOR_DOCUMENTOR_CORESCANNER_XSLPATH","system/cur-imvertor-filepath") : false; + succeeds = succeeds ? transformer.transformStep("system/cur-imvertor-filepath","properties/IMVERTOR_DOCUMENTOR_COREMODES_FILE", "properties/IMVERTOR_DOCUMENTOR_COREMODES_XSLPATH","system/cur-imvertor-filepath") : false; + succeeds = succeeds ? transformer.transformStep("system/cur-imvertor-filepath","properties/IMVERTOR_DOCUMENTOR_XHTMLTORESPEC_FILE", "properties/IMVERTOR_DOCUMENTOR_XHTMLTORESPEC_XSLPATH","system/cur-imvertor-filepath") : false; + } + if (succeeds) { + + // kopieer documentor configuratie naar de cat folder. Eerst de standaard "Imvertor" files, en daaroverheen de owner files. + AnyFolder target = new AnyFolder(configurator.getWorkFolder() + "/app/cat/documentor"); + target.mkdirs(); + AnyFolder imvertorFolder = new AnyFolder(configurator.getBaseFolder(), "input" + File.separator + "Imvertor/cfg/docrules/documentor"); // waaronder default.css en default.js + imvertorFolder.copy(target); + AnyFolder ownerFolder = new AnyFolder(configurator.getInputFolder() + "/cfg/docrules/documentor"); + if (ownerFolder.isDirectory()) + ownerFolder.copy(target); + else + runner.warn(logger, "Documentor has not been configured for \""+ configurator.getXParm("cli/owner") +"\". Please contact your system administrator."); + + // kopieer de gecachte versie van de respec config javascript naar de js folder + AnyFolder cacheFolder = new AnyFolder(configurator.getBaseFolder() + "/etc/respec/cache/" + configurator.getXParm("documentor/respec-config")); + AnyFolder jsFolder = new AnyFolder(target + "/js"); + cacheFolder.copy(jsFolder); } } - */ - } + configurator.setXParm("system/cur-imvertor-filepath", lastModeldocFile); + + if (succeeds) { + // we hebben nu het hele document in respec format, met daarin de catalogus. Plaats dit document als body van het Respec resultaat document. + if (configurator.isTrue("cli","fullrespec", false)) { + // process complete report + transformer.setXslParm("catalog-only", "false"); + succeeds = succeeds ? transformer.transformStep("system/cur-imvertor-filepath","properties/WORK_RESPEC_FILE", "properties/IMVERTOR_METAMODEL_" + dr + "_MODELDOC_RESPEC_XSLPATH") : false; + + // als de fn is "index", vervang dan de extensie door (index.)html + String fullExt = (fn.equals("index")) ? "html" : "respec.full.html"; + if (succeeds) processDoc(fn,fullExt,"appinfo/full-respec-documentation-filename","properties/WORK_RESPEC_FILE","none"); + } + + // process catalog only, save as HTML + transformer.setXslParm("catalog-only", "true"); + succeeds = succeeds ? transformer.transformStep("system/cur-imvertor-filepath","properties/WORK_RESPEC_FILE", "properties/IMVERTOR_METAMODEL_" + dr + "_MODELDOC_RESPEC_XSLPATH") : false; + if (succeeds) processDoc(fn,"respec.html","appinfo/respec-documentation-filename","properties/WORK_RESPEC_FILE",configurator.getXParm("cli/passoffice",false)); + } + + }//respec } else { runner.error(logger,"No (valid) office variant specified: " + vr.toString()); succeeds = false; @@ -276,8 +349,76 @@ private void passGIThub(File officeFile) throws Exception { } private boolean transformDocx(AnyFile mswordFile) throws Exception { - //TODO + WordFile infile = new WordFile(mswordFile); + XmlFile outfile = new XmlFile(mswordFile.getCanonicalPath() + ".xhtml"); - return true; + runner.info(logger,"Processing " + infile.getName()); + + Transformer transformer = new Transformer(); + + boolean succeeds = true; + + succeeds = succeeds ? infile.correctCodeSpaces() : false; + + succeeds = succeeds? infile.toXhtmlFile(outfile) : false; + + if (succeeds) { + // transformeer die XHTML naar iets bruikbaars, extraheer ook meteen respec properties + transformer.setXslParm("msword-file-path", outfile.getCanonicalPath()); + transformer.setXslParm("msword-file-name", outfile.getNameNoExtension()); + configurator.setXParm("system/cur-imvertor-filepath", outfile.getCanonicalPath()); + succeeds = succeeds ? transformer.transformStep("system/cur-imvertor-filepath","properties/IMVERTOR_DOCUMENTOR_FILEPREPARE_FILE", "properties/IMVERTOR_DOCUMENTOR_FILEPREPARE_XSLPATH","system/cur-imvertor-filepath") : false; + succeeds = succeeds ? transformer.transformStep("system/cur-imvertor-filepath","properties/IMVERTOR_DOCUMENTOR_FILEFINALIZE_FILE", "properties/IMVERTOR_DOCUMENTOR_FILEFINALIZE_XSLPATH","system/cur-imvertor-filepath") : false; + // vervang het file met de aangepaste XHTML file + (new AnyFile(configurator.getXParm("properties/IMVERTOR_DOCUMENTOR_FILEFINALIZE_FILE"))).copyFile(outfile); + } + return succeeds; } + + private boolean copyFilesToModulefolder(String workSubFolderPath, String modelName, boolean recurse, boolean mustExist) throws Exception { + + // workfolder is gemaakt; alle MsWord bestanden omzetten naar XHTML + AnyFolder workSubFolder = new AnyFolder(workSubFolderPath); + workSubFolderPath = workSubFolder.getCanonicalPath(); // forward slash correctie + if (workSubFolder.isDirectory()) { + // eerste slag: alle docx files transformeren naar standaard XHTML vorm. + Iterator it1 = workSubFolder.listFilesToVector(recurse).iterator(); + boolean succeeds = true; + while (it1.hasNext()) { + String path = it1.next(); + AnyFile f = new AnyFile(path); + Boolean isMasterDoc = f.getParent().equals(workSubFolderPath) && f.getName().equals(modelName + ".docx"); + String fileUri = f.toURI().toString(); + // Kies de te verwerken bestanden: het moet een docx file zijn, het is de masterdoc of het is een lokaal subdocument. Sla alle msword werkbestanden over. + if (f.getExtension().equals("docx") && (isMasterDoc || StringUtils.contains(fileUri,"/sections/")) && !StringUtils.startsWith(f.getName(),"~")) + succeeds = succeeds ? transformDocx(f) : false ; + } + // tweede slag: alles kopieren naar module folder + Iterator it2 = workSubFolder.listFilesToVector(recurse).iterator(); + while (it2.hasNext()) { + AnyFile f = new AnyFile(it2.next()); + String fileName = f.getName(); + String fileUri = f.toURI().toString(); + + // Kopieer de msword resultaten en de include files naar de module folder. + if (f.isFile()) { + Boolean isWordFile = StringUtils.endsWith(fileName,".docx.xhtml"); + Boolean isIncludeFile = StringUtils.contains(fileUri,"/include/"); + if (isWordFile || isIncludeFile) { + String filepath = (isWordFile) ? moduleFolder + "/" + fileName : configurator.getWorkFolder() + "/app/cat/inc/" + fileName; + AnyFile moduleFile = new AnyFile(filepath); + if (moduleFile.isFile()) { + runner.error(logger, "Duplicate file name in documentor input: " + fileName); + succeeds = false; + } else + f.copyFile(moduleFile); + } + } + } + + return succeeds; + } else + return !mustExist; + } + } diff --git a/src/main/java/nl/imvertor/common/Configurator.java b/src/main/java/nl/imvertor/common/Configurator.java index 63120f260..18ee6f288 100644 --- a/src/main/java/nl/imvertor/common/Configurator.java +++ b/src/main/java/nl/imvertor/common/Configurator.java @@ -250,6 +250,10 @@ public AnyFolder getBaseFolder() { public AnyFolder getWorkFolder() { return workFolder; } + + public AnyFolder getInputFolder() { + return inputFolder; + } public AnyFolder getWorkFolder(String subfolderName) { return new AnyFolder(workFolder,subfolderName); @@ -1040,7 +1044,7 @@ private void loadFromPropertyFile(String filePath) throws Exception { String optionName = e.nextElement().toString(); String value = properties.getProperty(optionName); // process file properties in context of the current file - if (optionName.equals("umlfile") | optionName.equals("zipfile") | optionName.equals("hisfile")) { + if (optionName.equals("umlfile") | optionName.equals("zipfile") | optionName.equals("hisfile") | optionName.equals("documentorfile")) { File parent = (new File(filePath)).getParentFile(); if (AnyFile.isAbsolutePath(value)) value = (new File(value)).getCanonicalPath(); diff --git a/src/main/java/nl/imvertor/common/file/HttpFile.java b/src/main/java/nl/imvertor/common/file/HttpFile.java index 9e1bde6f7..e1ac7755d 100644 --- a/src/main/java/nl/imvertor/common/file/HttpFile.java +++ b/src/main/java/nl/imvertor/common/file/HttpFile.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.net.URI; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -12,6 +13,7 @@ import java.util.Map; import java.util.Map.Entry; +import org.apache.commons.io.IOUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; @@ -220,13 +222,7 @@ public int getStatus() { return status; } public String getResponseBody(HttpResponse response) throws Exception, IOException { - BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); - String inputLine; - StringBuffer responseText = new StringBuffer(); - while ((inputLine = in.readLine()) != null) - responseText.append(inputLine); - in.close(); - return responseText.toString(); + return IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); } } diff --git a/src/main/java/nl/imvertor/common/file/WordFile.java b/src/main/java/nl/imvertor/common/file/WordFile.java new file mode 100644 index 000000000..33469b9de --- /dev/null +++ b/src/main/java/nl/imvertor/common/file/WordFile.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2016 Dienst voor het kadaster en de openbare registers + * + * This file is part of Imvertor. + * + * Imvertor is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Imvertor is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Imvertor. If not, see . + * + */ + +package nl.imvertor.common.file; + +import java.io.File; +import java.net.URI; +import java.util.Base64; +import java.util.HashMap; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpHeaders; +import org.apache.log4j.Logger; +import org.json.JSONObject; + +import nl.imvertor.common.Configurator; +import nl.imvertor.common.Runner; +import nl.imvertor.common.Transformer; +import nl.imvertor.common.helper.OsExecutor; +import nl.imvertor.common.helper.OsExecutor.OsExecutorResultHandler; + +public class WordFile extends AnyFile { + + public static final Logger logger = Logger.getLogger(ExecFile.class); + private static final long serialVersionUID = 2409879811971148189L; + + public WordFile(String filepath) { + super(filepath); + } + public WordFile(File file) { + super(file.getAbsolutePath()); + } + public WordFile(File file, String subpath) { + super(file, subpath); + } + + /** + * Transform the Doc file to XHTML structure. + * This uses Pandoc. + * + * @return XmlFile + * @param filePath + * @throws Exception + */ + public boolean toXhtmlFile(XmlFile outFile) throws Exception { + + Configurator configurator = Configurator.getInstance(); + Runner runner = configurator.getRunner(); + boolean debugging = runner.getDebug("DOCUMENTOR"); + + String pandocServerUrl = configurator.getServerProperty("pandoc.server", false); + if (pandocServerUrl != null) { + // gebruik de pandoc server: https://pandoc.org/pandoc-server.html + + HttpFile localFile = new HttpFile(this); + + HashMap headerMap = new HashMap(); + //headerMap.put(HttpHeaders.AUTHORIZATION,"token " + OAUTH); + headerMap.put(HttpHeaders.ACCEPT, "application/octet-stream"); + headerMap.put(HttpHeaders.CONTENT_TYPE, "application/json"); + headerMap.put(HttpHeaders.CONTENT_ENCODING, getEncoding()); + + String payloadBase64 = Base64.getEncoder().encodeToString(this.getBinaryContent()); + String payload = "{" + + "\"from\": \"docx+styles\"," + + "\"to\": \"html\"," + + "\"indented-code-classes\": [" + + "\"Programmacode\"" + + "]," + + "\"section-divs\": true," + + "\"embed-resources\": true," + //+ "\"ipynb-output\": \"all\"," + + "\"standalone\": true," + + "\"variables\": {" + + "\"lang\": \"nl-NL\"," + + "\"title-meta\": \"NOTITLE\"" + + "}," + + "\"text\": \"" + payloadBase64 + "\"" + + "}"; + try { + String result = localFile.post(HttpFile.METHOD_POST_CONTENT, URI.create(pandocServerUrl), headerMap, null, new String[] {payload}); + if (StringUtils.startsWith(result,"<")) { + outFile.setContent(result); + return true; + } else { + runner.error(logger, "Documentor processing error: \"" + result + "\""); + return false; + } + } catch (Exception e) { + runner.error(logger, "Documentor server error: \"" + e.getMessage() + "\""); + } + return false; + } else { + // Implementatie van Pandoc omzetting naar XHTML. + + OsExecutor osExecutor = new OsExecutor(); + + String toolloc = (new AnyFile(configurator.getServerProperty("documentor.msword.transformer"))).getCanonicalPath(); // location of the tool + long osExecutorJobTimeout = Long.parseLong(configurator.getServerProperty("documentor.msword.transformer.timeout")); // location of the tool + boolean osExecutorInBackground = false; + + OsExecutorResultHandler osExecutorResult = null; + + /* + * Dit batch file doet het volgende + * - Bereid MsWord voor door roep o.a. pandoc aan en corrigeert allerlei + */ + CommandLine commandLine = new CommandLine(toolloc + "\\documentor.bat"); // TODO: *nix + commandLine.addArgument(this.getName()); // the docx file + commandLine.addArgument(toolloc); // the tool folder + commandLine.addArgument(this.getParent()); // The work folder + commandLine.addArgument(debugging ? "true" : "false"); // debugging? + + try { + osExecutorResult = osExecutor.osexec(commandLine, osExecutorJobTimeout, osExecutorInBackground); + osExecutorResult.waitFor(); + // assume the msword file * is transformed to *.xhtml + configurator.setXParm("appinfo/documentor-transformation-result", outFile.getName(),false); + return true; + + } catch (Exception e) { + if (osExecutorResult != null) + runner.error(logger, "Documentor exit value " + osExecutorResult.getExitValue() + ". " + osExecutorResult.getException().getMessage()); + else + runner.error(logger, e.getMessage()); + } + } + return false; + + } + + /* + * Uitlezen van msword gaat niet altijd goed; in preserveSpace secties worden leading blanks niet goed verwerkt. Vervang deze door harde spaties. + */ + public boolean correctCodeSpaces() throws Exception{ + Configurator configurator = Configurator.getInstance(); + try { + ZipFile thisFile = new ZipFile(this); + AnyFolder tempFolder = configurator.getWorkFolder("documentor/msword"); + thisFile.decompress(tempFolder); + // run stylesheet om de spaties in code vast te zetten + XmlFile wordFile = new XmlFile(tempFolder,"/word/document.xml"); + XmlFile outFile = new XmlFile(tempFolder,"/word/document.xml.transformed"); + XslFile xslFile = new XslFile(configurator.getBaseFolder() + "/xsl/OfficeCompiler/Imvert2documentor-msword-fixes.xsl"); + Transformer transformer = new Transformer(); + transformer.transform(wordFile, outFile, xslFile, "filefix"); + // zet het resultaat van de transformatie op de plek van het input document + outFile.copyFile(wordFile); + outFile.delete(); + // Maak het MdWord bestand opnieuw aan door de tijdelijke folder weer te zippen. + thisFile.compress(tempFolder); + return true; + } catch (Exception e) { + configurator.getRunner().error(logger,"Cannot fix MsWord program code fragment(s)",e); + return false; + } + } +} diff --git a/src/main/java/nl/imvertor/common/file/ZipFile.java b/src/main/java/nl/imvertor/common/file/ZipFile.java index b368ced63..40b33caf3 100644 --- a/src/main/java/nl/imvertor/common/file/ZipFile.java +++ b/src/main/java/nl/imvertor/common/file/ZipFile.java @@ -21,19 +21,12 @@ package nl.imvertor.common.file; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Vector; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; @@ -63,6 +56,7 @@ public ZipFile(String zipFilePath) throws IOException { } public ZipFile(File file) throws IOException { super(file); + fileList = new ArrayList(); } public ZipFile(File folder, String file) throws IOException { super(folder, file); @@ -79,9 +73,7 @@ public ZipFile(File folder, String file) throws IOException { */ public void compress(File folderToCompress) throws Exception { if (folderToCompress.isDirectory()) { - sourceFolder = folderToCompress.getAbsolutePath(); - generateFileList(folderToCompress); - zipIt(); + ZipUtils.zipDirectory(folderToCompress, this); } else throw new Exception("Source folder for zip is not a folder: " + folderToCompress); } @@ -94,113 +86,9 @@ public void compress(File folderToCompress) throws Exception { * @throws Exception */ public void decompress(AnyFolder targetFolder) throws Exception { - unZipIt(this.getAbsolutePath(),targetFolder.getAbsolutePath(),null); - } - public void decompress(AnyFolder targetFolder,Pattern requestedFilePattern) throws Exception { - if (targetFolder.isFile()) - throw new Exception("Cannot decompress to a file: " + targetFolder); - if (!targetFolder.exists() ) - targetFolder.mkdirs(); - unZipIt(this.getAbsolutePath(),targetFolder.getAbsolutePath(),requestedFilePattern); + ZipUtils.unzipFile(this, targetFolder); } - - /** - * Traverse a folder and get all files, - * and add the file into fileList - * @param node file or folder - */ - // adapted from http://www.mkyong.com/java/how-to-compress-files-in-zip-format/ - private void generateFileList(File node){ - - //add file only - if(node.isFile()) { - fileList.add(generateZipEntry(node.getAbsoluteFile().toString())); - } - if(node.isDirectory()){ - String[] subNote = node.list(); - for(String filename : subNote){ - generateFileList(new File(node, filename)); - } - } - } - - /** - * Format the file path for zip - * @param file file path - * @return Formatted file path - */ - private String generateZipEntry(String file){ - return file.substring(sourceFolder.length()+1, file.length()); - } - - /** - * Zip it - * @throws IOException - */ - // adapted from http://www.mkyong.com/java/how-to-compress-files-in-zip-format/ - private void zipIt() throws IOException { - byte[] buffer = new byte[1024]; - FileOutputStream fos = new FileOutputStream(this); - ZipOutputStream zos = new ZipOutputStream(fos); - for(String file : this.fileList){ - ZipEntry ze = new ZipEntry(file); - zos.putNextEntry(ze); - FileInputStream in = new FileInputStream(sourceFolder + File.separator + file); - int len; - while ((len = in.read(buffer)) > 0) { - zos.write(buffer, 0, len); - } - in.close(); - } - zos.closeEntry(); - zos.close(); - } - - /** - * Unzip it - * @param zipFile input zip file - * @param outputFolder zip file output folder - * @param requestedFilePattern Pattern to match the file name. - * - * @throws Exception - */ - private void unZipIt(String zipFile, String outputFolder, Pattern requestedFilePattern) throws Exception{ - - byte[] buffer = new byte[1024]; - - //create output folder is not exists - AnyFolder folder = new AnyFolder(outputFolder); - folder.mkdir(); - - //get the zip file content - ZipInputStream zis = - new ZipInputStream(new FileInputStream(zipFile)); - //get the zipped file list entry - ZipEntry ze = zis.getNextEntry(); - - while(ze!=null){ - if (!ze.isDirectory()) { - String fileName = ze.getName(); - // if the pattern specified, use a matcher. Otherwise accept any file. - Matcher m = (requestedFilePattern != null) ? requestedFilePattern.matcher(fileName) : null; - if (requestedFilePattern == null || m.find()) { - File newFile = new File(outputFolder + File.separator + fileName); - //create all non exists folders - //else you will hit FileNotFoundException for compressed folder - new File(newFile.getParent()).mkdirs(); - FileOutputStream fos = new FileOutputStream(newFile); - int len; - while ((len = zis.read(buffer)) > 0) { - fos.write(buffer, 0, len); - } - fos.close(); - } - } - ze = zis.getNextEntry(); - } - zis.closeEntry(); - zis.close(); - } + /** * Create an XML serialization in a folder that will hold * 1/ a single xml file content.xml diff --git a/src/main/java/nl/imvertor/common/file/ZipUtils.java b/src/main/java/nl/imvertor/common/file/ZipUtils.java new file mode 100644 index 000000000..6490b4641 --- /dev/null +++ b/src/main/java/nl/imvertor/common/file/ZipUtils.java @@ -0,0 +1,135 @@ +package nl.imvertor.common.file; + +/* + * 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Enumeration; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +public class ZipUtils { + + public static void zip(File directory, File base, ZipOutputStream zos) throws IOException { + File[] files = directory.listFiles(); + byte[] buffer = new byte[8192]; + int read = 0; + for (int i=0, n=files.length; i e = archive.entries(); + while (e.hasMoreElements()) { + ZipEntry entry = (ZipEntry) e.nextElement(); + File file = new File(extractTo, entry.getName()); + if (entry.isDirectory()) { + if (!file.exists()) { + file.mkdirs(); + } // else nothing to do + } else { + if (!file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + InputStream in = archive.getInputStream(entry); + BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file)); + try { + byte[] buffer = new byte[8192]; + int read; + while (-1 != (read = in.read(buffer))) { + out.write(buffer, 0, read); + } + } finally { + in.close(); + out.close(); + } + } + } + } finally { + archive.close(); + } + } + + public static void unzipStream(InputStream is, File extractTo) throws IOException { + byte[] buffer = new byte[8192]; + int size; + ZipInputStream zis = new ZipInputStream(is); + ZipEntry entry; + try { + while ((entry = zis.getNextEntry()) != null) { + File file = new File(extractTo, entry.getName()); + if (entry.isDirectory()) { + if (!file.exists()) { + file.mkdirs(); + } + } else { + if (!file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); + try { + while ((size = zis.read(buffer, 0, buffer.length)) != -1) { + bos.write(buffer, 0, size); + } + bos.flush(); + } finally { + zis.closeEntry(); + bos.close(); + } + } + } + } finally { + zis.close(); + } + } + +} \ No newline at end of file diff --git a/src/main/java/nl/imvertor/common/xsl/extensions/ImvertorCalculateHashlabel.java b/src/main/java/nl/imvertor/common/xsl/extensions/ImvertorCalculateHashlabel.java new file mode 100644 index 000000000..c98f75468 --- /dev/null +++ b/src/main/java/nl/imvertor/common/xsl/extensions/ImvertorCalculateHashlabel.java @@ -0,0 +1,90 @@ +/* + * $HeadURL$ + * $LastChangedRevision$ + * $LastChangedDate$ + * $LastChangedBy$ + */ + +package nl.imvertor.common.xsl.extensions; + +import net.sf.saxon.expr.XPathContext; +import net.sf.saxon.lib.ExtensionFunctionCall; +import net.sf.saxon.lib.ExtensionFunctionDefinition; +import net.sf.saxon.om.Sequence; +import net.sf.saxon.om.StructuredQName; +import net.sf.saxon.trans.XPathException; +import net.sf.saxon.value.SequenceType; +import net.sf.saxon.value.StringValue; +import nl.imvertor.common.Configurator; + +public class ImvertorCalculateHashlabel extends ExtensionFunctionDefinition { + + private static final StructuredQName qName = + new StructuredQName("", Configurator.NAMESPACE_EXTENSION_FUNCTIONS, "imvertorCalculateHashLabel"); + + public StructuredQName getFunctionQName() { + return qName; + } + + public int getMinimumNumberOfArguments() { + return 2; + } + + public int getMaximumNumberOfArguments() { + return 2; + } + + public SequenceType[] getArgumentTypes() { + return new SequenceType[] { SequenceType.SINGLE_STRING, SequenceType.SINGLE_STRING }; + } + + public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) { + return SequenceType.SINGLE_STRING; + } + + public ExtensionFunctionCall makeCallExpression() { + return new HashlabelCall(); + } + + private static class HashlabelCall extends ExtensionFunctionCall { + + /** + * Extension function. + * Create Hash on the string passed. Return a label (characters, digits,... based on the supplied pool of characters) or a full hash (digits) for the supplied string. + * + * @param string to create a hash label for + * @return string hash + * @throws Exception + */ + + /** + * Calculate Hashlabel on input data + */ + public static String calculateHashlabel(String s,String characters) { + int hash = s.hashCode() & 0xfffffff; // Maak het positief, gegenereerde hashes kunnen negatief zijn. - https://stackoverflow.com/questions/33219638/how-to-make-a-hashcodeinteger-value-positive + if (characters.length() > 0) + return subtract(hash,"",characters); + else + return String.valueOf(hash); + } + + private static String subtract(int seed, String result, String pool) { + int l = pool.length(); + int m = seed % l; + int r = seed / l; + String c = pool.substring(m,m + 1); + if (r > 0) + return result + c + subtract(r,result,pool); + else + return result + c; + } + + @Override + public Sequence call(XPathContext arg0, Sequence[] arguments) throws XPathException { + String s1 = arguments[0].head().getStringValue(); + String s2 = arguments[1].head().getStringValue(); + return StringValue.makeStringValue(calculateHashlabel(s1,s2)); + } + + } +} \ No newline at end of file diff --git a/src/main/resources/cfg/ConfigCompiler/parms.xml b/src/main/resources/cfg/ConfigCompiler/parms.xml index c4fc9fab1..59c2df74d 100644 --- a/src/main/resources/cfg/ConfigCompiler/parms.xml +++ b/src/main/resources/cfg/ConfigCompiler/parms.xml @@ -27,7 +27,7 @@ owner name - Name of the project owner + The owner of the configurations that are applied in a single Imvertor OS run. Typically an organization name. true diff --git a/src/main/resources/cfg/OfficeCompiler/parms.xml b/src/main/resources/cfg/OfficeCompiler/parms.xml index 031244a82..e6b7cb2ee 100644 --- a/src/main/resources/cfg/OfficeCompiler/parms.xml +++ b/src/main/resources/cfg/OfficeCompiler/parms.xml @@ -25,13 +25,13 @@ createoffice - html|doc|none + html | doc | none Create a documentation file in plain HTML, MsWord, or Respec format. By default, create none. false createofficevariant - msword/respec + msword | respec | documentor Specify the type of office file. Multiple formats are allowed, separate list by whitespace. When createoffice is set to html @@ -133,6 +133,14 @@ Yes if codelists and reference lists that have a location must be read dynamically from that location and included in the model documentation. false + + + modeldocfile + filepath + Path to the folder or zipfile holding the modeldoc files, i.e. profile and MsWord files and images used to create a full Respec. + false + file + @@ -148,6 +156,21 @@ Imvert2modeldoc-xhtml-respec.xsl + Imvert2documentor-file-prepare.xsl + ${system/work-imvert-folder-path}/imvertor.26.1.documentor-file-prepare.xhtml + + Imvert2documentor-file-finalize.xsl + ${system/work-imvert-folder-path}/imvertor.26.2.documentor-file-finalize.xhtml + + Imvert2documentor-core-scanner.xsl + ${system/work-imvert-folder-path}/imvertor.26.3.documentor-core-scanner.xhtml + + Imvert2documentor-core-modes.xsl + ${system/work-imvert-folder-path}/imvertor.26.4.documentor-core-modes.xhtml + + Imvert2documentor-respec-xhtml-to-respec.xsl + ${system/work-imvert-folder-path}/imvertor.26.5.documentor-respec-xhtml-to-respec.xhtml + Imvert2modeldoc-KING-MIM-11-SIM.xsl Imvert2modeldoc-KING-MIM-11-SIM-html-msword.xsl @@ -252,6 +275,9 @@ Imvert2modeldoc-Kadaster-MIM-11-html-msword.xsl Imvert2modeldoc-Kadaster-MIM-11-html-respec.xsl + Imvert2modeldoc-Armatiek-MIM-12-CONCEPTUAL.xsl + Imvert2modeldoc-Armatiek-MIM-12-CONCEPTUAL-html-respec.xsl + Imvert2modeldoc-EIGENAAR-MIM-12-CONCEPTUAL.xsl Imvert2modeldoc-EIGENAAR-MIM-12-CONCEPTUAL-html-respec.xsl Imvert2modeldoc-EIGENAAR-MIM-12-CONCEPTUAL-html-msword.xsl diff --git a/src/main/resources/cfg/Validator/parms.xml b/src/main/resources/cfg/Validator/parms.xml index 592733a9d..c2503ebeb 100644 --- a/src/main/resources/cfg/Validator/parms.xml +++ b/src/main/resources/cfg/Validator/parms.xml @@ -47,6 +47,12 @@ Yes if the notes fields that are required must be checked (for content) true + + allowemptymodel + yes|no + Yes if the model or any model domain may be empty; this is feasible in development phases + false + stub_requiresalias yes|no @@ -371,6 +377,22 @@ Imvert2validation-MIM-11.xsl Imvert2validation-BRO-MIM-1-LOGICAL.xsl + + + Imvert2canonical.xsl + Imvert2canonical-MIM-10.xsl + Imvert2canonical-MIM-11.xsl + Imvert2canonical-MIM-12.xsl + + Imvert2validation.xsl + Imvert2validation-MIM-10.xsl + Imvert2validation-MIM-11.xsl + Imvert2validation-MIM-12.xsl + - Imvert2canonical.xsl - Imvert2canonical-MIM-10.xsl - Imvert2canonical-MIM-11.xsl - Imvert2canonical-MIM-12.xsl - - Imvert2validation.xsl - Imvert2validation-MIM-10.xsl - Imvert2validation-MIM-11.xsl - Imvert2validation-MIM-12.xsl - |$))/,he=X("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n *)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$))","i").replace("comment",fe).replace("tag",pe).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),me=X(ce).replace("hr",ie).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",pe).getRegex(),ge={blockquote:X(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",me).getRegex(),code:/^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,def:ue,fences:/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,heading:/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,hr:ie,html:he,lheading:ae,list:de,newline:/^(?: *(?:\n|$))+/,paragraph:me,table:ee,text:/^[^\n]+/},be=X("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",ie).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",pe).getRegex(),we={...ge,table:be,paragraph:X(ce).replace("hr",ie).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",be).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",pe).getRegex()},ye={...ge,html:X("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",fe).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:ee,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:X(ce).replace("hr",ie).replace("heading"," *#{1,6} *[^\n]").replace("lheading",ae).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},ve=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,$e=/^( {2,}|\\)\n(?!\s*$)/,xe="\\p{P}\\p{S}",ke=X(/^((?![*_])[\spunctuation])/,"u").replace(/punctuation/g,xe).getRegex(),_e=X(/^(?:\*+(?:((?!\*)[punct])|[^\s*]))|^_+(?:((?!_)[punct])|([^\s_]))/,"u").replace(/punct/g,xe).getRegex(),Ee=X("^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)[punct](\\*+)(?=[\\s]|$)|[^punct\\s](\\*+)(?!\\*)(?=[punct\\s]|$)|(?!\\*)[punct\\s](\\*+)(?=[^punct\\s])|[\\s](\\*+)(?!\\*)(?=[punct])|(?!\\*)[punct](\\*+)(?!\\*)(?=[punct])|[^punct\\s](\\*+)(?=[^punct\\s])","gu").replace(/punct/g,xe).getRegex(),Ce=X("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)[punct](_+)(?=[\\s]|$)|[^punct\\s](_+)(?!_)(?=[punct\\s]|$)|(?!_)[punct\\s](_+)(?=[^punct\\s])|[\\s](_+)(?!_)(?=[punct])|(?!_)[punct](_+)(?!_)(?=[punct])","gu").replace(/punct/g,xe).getRegex(),Se=X(/\\([punct])/,"gu").replace(/punct/g,xe).getRegex(),Le=X(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),Re=X(fe).replace("(?:--\x3e|$)","--\x3e").getRegex(),Ae=X("^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment",Re).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),Te=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,Pe=X(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/).replace("label",Te).replace("href",/<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),Ie=X(/^!?\[(label)\]\[(ref)\]/).replace("label",Te).replace("ref",le).getRegex(),De=X(/^!?\[(ref)\](?:\[\])?/).replace("ref",le).getRegex(),Ne={_backpedal:ee,anyPunctuation:Se,autolink:Le,blockSkip:/\[[^[\]]*?\]\([^\(\)]*?\)|`[^`]*?`|<[^<>]*?>/g,br:$e,code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,del:ee,emStrongLDelim:_e,emStrongRDelimAst:Ee,emStrongRDelimUnd:Ce,escape:ve,link:Pe,nolink:De,punctuation:ke,reflink:Ie,reflinkSearch:X("reflink|nolink(?!\\()","g").replace("reflink",Ie).replace("nolink",De).getRegex(),tag:Ae,text:/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\t+" ".repeat(n.length)));e;)if(!(this.options.extensions&&this.options.extensions.block&&this.options.extensions.block.some((r=>!!(n=r.call({lexer:this},e,t))&&(e=e.substring(n.raw.length),t.push(n),!0)))))if(n=this.tokenizer.space(e))e=e.substring(n.raw.length),1===n.raw.length&&t.length>0?t[t.length-1].raw+="\n":t.push(n);else if(n=this.tokenizer.code(e))e=e.substring(n.raw.length),r=t[t.length-1],!r||"paragraph"!==r.type&&"text"!==r.type?t.push(n):(r.raw+="\n"+n.raw,r.text+="\n"+n.text,this.inlineQueue[this.inlineQueue.length-1].src=r.text);else if(n=this.tokenizer.fences(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.heading(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.hr(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.blockquote(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.list(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.html(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.def(e))e=e.substring(n.raw.length),r=t[t.length-1],!r||"paragraph"!==r.type&&"text"!==r.type?this.tokens.links[n.tag]||(this.tokens.links[n.tag]={href:n.href,title:n.title}):(r.raw+="\n"+n.raw,r.text+="\n"+n.raw,this.inlineQueue[this.inlineQueue.length-1].src=r.text);else if(n=this.tokenizer.table(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.lheading(e))e=e.substring(n.raw.length),t.push(n);else{if(o=e,this.options.extensions&&this.options.extensions.startBlock){let t=1/0;const n=e.slice(1);let r;this.options.extensions.startBlock.forEach((e=>{r=e.call({lexer:this},n),"number"==typeof r&&r>=0&&(t=Math.min(t,r))})),t<1/0&&t>=0&&(o=e.substring(0,t+1))}if(this.state.top&&(n=this.tokenizer.paragraph(o)))r=t[t.length-1],i&&"paragraph"===r.type?(r.raw+="\n"+n.raw,r.text+="\n"+n.text,this.inlineQueue.pop(),this.inlineQueue[this.inlineQueue.length-1].src=r.text):t.push(n),i=o.length!==e.length,e=e.substring(n.raw.length);else if(n=this.tokenizer.text(e))e=e.substring(n.raw.length),r=t[t.length-1],r&&"text"===r.type?(r.raw+="\n"+n.raw,r.text+="\n"+n.text,this.inlineQueue.pop(),this.inlineQueue[this.inlineQueue.length-1].src=r.text):t.push(n);else if(e){const t="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(t);break}throw new Error(t)}}return this.state.top=!0,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){let n,r,o,i,s,a,c=e;if(this.tokens.links){const e=Object.keys(this.tokens.links);if(e.length>0)for(;null!=(i=this.tokenizer.rules.inline.reflinkSearch.exec(c));)e.includes(i[0].slice(i[0].lastIndexOf("[")+1,-1))&&(c=c.slice(0,i.index)+"["+"a".repeat(i[0].length-2)+"]"+c.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;null!=(i=this.tokenizer.rules.inline.blockSkip.exec(c));)c=c.slice(0,i.index)+"["+"a".repeat(i[0].length-2)+"]"+c.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);for(;null!=(i=this.tokenizer.rules.inline.anyPunctuation.exec(c));)c=c.slice(0,i.index)+"++"+c.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);for(;e;)if(s||(a=""),s=!1,!(this.options.extensions&&this.options.extensions.inline&&this.options.extensions.inline.some((r=>!!(n=r.call({lexer:this},e,t))&&(e=e.substring(n.raw.length),t.push(n),!0)))))if(n=this.tokenizer.escape(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.tag(e))e=e.substring(n.raw.length),r=t[t.length-1],r&&"text"===n.type&&"text"===r.type?(r.raw+=n.raw,r.text+=n.text):t.push(n);else if(n=this.tokenizer.link(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.reflink(e,this.tokens.links))e=e.substring(n.raw.length),r=t[t.length-1],r&&"text"===n.type&&"text"===r.type?(r.raw+=n.raw,r.text+=n.text):t.push(n);else if(n=this.tokenizer.emStrong(e,c,a))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.codespan(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.br(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.del(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.autolink(e))e=e.substring(n.raw.length),t.push(n);else if(this.state.inLink||!(n=this.tokenizer.url(e))){if(o=e,this.options.extensions&&this.options.extensions.startInline){let t=1/0;const n=e.slice(1);let r;this.options.extensions.startInline.forEach((e=>{r=e.call({lexer:this},n),"number"==typeof r&&r>=0&&(t=Math.min(t,r))})),t<1/0&&t>=0&&(o=e.substring(0,t+1))}if(n=this.tokenizer.inlineText(o))e=e.substring(n.raw.length),"_"!==n.raw.slice(-1)&&(a=n.raw.slice(-1)),s=!0,r=t[t.length-1],r&&"text"===r.type?(r.raw+=n.raw,r.text+=n.text):t.push(n);else if(e){const t="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(t);break}throw new Error(t)}}else e=e.substring(n.raw.length),t.push(n);return t}}class Fe{options;constructor(e){this.options=e||q}code(e,t,n){const r=(t||"").match(/^\S*/)?.[0];return e=e.replace(/\n$/,"")+"\n",r?'
'+(n?e:Y(e,!0))+"
\n":"
"+(n?e:Y(e,!0))+"
\n"}blockquote(e){return`
\n${e}
\n`}html(e,t){return e}heading(e,t,n){return`${e}\n`}hr(){return"
\n"}list(e,t,n){const r=t?"ol":"ul";return"<"+r+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+"\n"}listitem(e,t,n){return`
  • ${e}
  • \n`}checkbox(e){return"'}paragraph(e){return`

    ${e}

    \n`}table(e,t){return t&&(t=`${t}`),"\n\n"+e+"\n"+t+"
    \n"}tablerow(e){return`\n${e}\n`}tablecell(e,t){const n=t.header?"th":"td";return(t.align?`<${n} align="${t.align}">`:`<${n}>`)+e+`\n`}strong(e){return`${e}`}em(e){return`${e}`}codespan(e){return`${e}`}br(){return"
    "}del(e){return`${e}`}link(e,t,n){const r=J(e);if(null===r)return n;let o='",o}image(e,t,n){const r=J(e);if(null===r)return n;let o=`${n}0&&"paragraph"===n.tokens[0].type?(n.tokens[0].text=e+" "+n.tokens[0].text,n.tokens[0].tokens&&n.tokens[0].tokens.length>0&&"text"===n.tokens[0].tokens[0].type&&(n.tokens[0].tokens[0].text=e+" "+n.tokens[0].tokens[0].text)):n.tokens.unshift({type:"text",text:e+" "}):a+=e+" "}a+=this.parse(n.tokens,i),s+=this.renderer.listitem(a,o,!!r)}n+=this.renderer.list(s,t,r);continue}case"html":{const e=o;n+=this.renderer.html(e.text,e.block);continue}case"paragraph":{const e=o;n+=this.renderer.paragraph(this.parseInline(e.tokens));continue}case"text":{let i=o,s=i.tokens?this.parseInline(i.tokens):i.text;for(;r+1{const o=e[r].flat(1/0);n=n.concat(this.walkTokens(o,t))})):e.tokens&&(n=n.concat(this.walkTokens(e.tokens,t)))}}return n}use(...e){const t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach((e=>{const n={...e};if(n.async=this.defaults.async||n.async||!1,e.extensions&&(e.extensions.forEach((e=>{if(!e.name)throw new Error("extension name required");if("renderer"in e){const n=t.renderers[e.name];t.renderers[e.name]=n?function(...t){let r=e.renderer.apply(this,t);return!1===r&&(r=n.apply(this,t)),r}:e.renderer}if("tokenizer"in e){if(!e.level||"block"!==e.level&&"inline"!==e.level)throw new Error("extension level must be 'block' or 'inline'");const n=t[e.level];n?n.unshift(e.tokenizer):t[e.level]=[e.tokenizer],e.start&&("block"===e.level?t.startBlock?t.startBlock.push(e.start):t.startBlock=[e.start]:"inline"===e.level&&(t.startInline?t.startInline.push(e.start):t.startInline=[e.start]))}"childTokens"in e&&e.childTokens&&(t.childTokens[e.name]=e.childTokens)})),n.extensions=t),e.renderer){const t=this.defaults.renderer||new Fe(this.defaults);for(const n in e.renderer){if(!(n in t))throw new Error(`renderer '${n}' does not exist`);if("options"===n)continue;const r=n,o=e.renderer[r],i=t[r];t[r]=(...e)=>{let n=o.apply(t,e);return!1===n&&(n=i.apply(t,e)),n||""}}n.renderer=t}if(e.tokenizer){const t=this.defaults.tokenizer||new oe(this.defaults);for(const n in e.tokenizer){if(!(n in t))throw new Error(`tokenizer '${n}' does not exist`);if(["options","rules","lexer"].includes(n))continue;const r=n,o=e.tokenizer[r],i=t[r];t[r]=(...e)=>{let n=o.apply(t,e);return!1===n&&(n=i.apply(t,e)),n}}n.tokenizer=t}if(e.hooks){const t=this.defaults.hooks||new We;for(const n in e.hooks){if(!(n in t))throw new Error(`hook '${n}' does not exist`);if("options"===n)continue;const r=n,o=e.hooks[r],i=t[r];We.passThroughHooks.has(n)?t[r]=e=>{if(this.defaults.async)return Promise.resolve(o.call(t,e)).then((e=>i.call(t,e)));const n=o.call(t,e);return i.call(t,n)}:t[r]=(...e)=>{let n=o.apply(t,e);return!1===n&&(n=i.apply(t,e)),n}}n.hooks=t}if(e.walkTokens){const t=this.defaults.walkTokens,r=e.walkTokens;n.walkTokens=function(e){let n=[];return n.push(r.call(this,e)),t&&(n=n.concat(t.call(this,e))),n}}this.defaults={...this.defaults,...n}})),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return Ue.lex(e,t??this.defaults)}parser(e,t){return He.parse(e,t??this.defaults)}#e(e,t){return(n,r)=>{const o={...r},i={...this.defaults,...o};!0===this.defaults.async&&!1===o.async&&(i.silent||console.warn("marked(): The async option was set to true by an extension. The async: false option sent to parse will be ignored."),i.async=!0);const s=this.#t(!!i.silent,!!i.async);if(null==n)return s(new Error("marked(): input parameter is undefined or null"));if("string"!=typeof n)return s(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(n)+", string expected"));if(i.hooks&&(i.hooks.options=i),i.async)return Promise.resolve(i.hooks?i.hooks.preprocess(n):n).then((t=>e(t,i))).then((e=>i.hooks?i.hooks.processAllTokens(e):e)).then((e=>i.walkTokens?Promise.all(this.walkTokens(e,i.walkTokens)).then((()=>e)):e)).then((e=>t(e,i))).then((e=>i.hooks?i.hooks.postprocess(e):e)).catch(s);try{i.hooks&&(n=i.hooks.preprocess(n));let r=e(n,i);i.hooks&&(r=i.hooks.processAllTokens(r)),i.walkTokens&&this.walkTokens(r,i.walkTokens);let o=t(r,i);return i.hooks&&(o=i.hooks.postprocess(o)),o}catch(e){return s(e)}}}#t(e,t){return n=>{if(n.message+="\nPlease report this to https://github.com/markedjs/marked.",e){const e="

    An error occurred:

    "+Y(n.message+"",!0)+"
    ";return t?Promise.resolve(e):e}if(t)return Promise.reject(n);throw n}}};function Ze(e,t){return Ve.parse(e,t)}Ze.options=Ze.setOptions=function(e){return Ve.setOptions(e),Ze.defaults=Ve.defaults,U(Ze.defaults),Ze},Ze.getDefaults=M,Ze.defaults=q,Ze.use=function(...e){return Ve.use(...e),Ze.defaults=Ve.defaults,U(Ze.defaults),Ze},Ze.walkTokens=function(e,t){return Ve.walkTokens(e,t)},Ze.parseInline=Ve.parseInline,Ze.Parser=He,Ze.parser=He.parse,Ze.Renderer=Fe,Ze.TextRenderer=Be,Ze.Lexer=Ue,Ze.lexer=Ue.lex,Ze.Tokenizer=oe,Ze.Hooks=We,Ze.parse=Ze,Ze.options,Ze.setOptions,Ze.use,Ze.walkTokens,Ze.parseInline,He.parse,Ue.lex;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;function Ye(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var Ke,Ge={exports:{}};Ke=Ge,function(e,t){Ke.exports=t()}(0,(function(){var e=[],t=[],n={},r={},o={};function i(e){return"string"==typeof e?new RegExp("^"+e+"$","i"):e}function s(e,t){return e===t?t:e===e.toLowerCase()?t.toLowerCase():e===e.toUpperCase()?t.toUpperCase():e[0]===e[0].toUpperCase()?t.charAt(0).toUpperCase()+t.substr(1).toLowerCase():t.toLowerCase()}function a(e,t){return e.replace(t[0],(function(n,r){var o,i,a=(o=t[1],i=arguments,o.replace(/\$(\d{1,2})/g,(function(e,t){return i[t]||""})));return s(""===n?e[r-1]:n,a)}))}function c(e,t,r){if(!e.length||n.hasOwnProperty(e))return t;for(var o=r.length;o--;){var i=r[o];if(i[0].test(t))return a(t,i)}return t}function l(e,t,n){return function(r){var o=r.toLowerCase();return t.hasOwnProperty(o)?s(r,o):e.hasOwnProperty(o)?s(r,e[o]):c(o,r,n)}}function u(e,t,n,r){return function(r){var o=r.toLowerCase();return!!t.hasOwnProperty(o)||!e.hasOwnProperty(o)&&c(o,o,n)===o}}function d(e,t,n){return(n?t+" ":"")+(1===t?d.singular(e):d.plural(e))}return d.plural=l(o,r,e),d.isPlural=u(o,r,e),d.singular=l(r,o,t),d.isSingular=u(r,o,t),d.addPluralRule=function(t,n){e.push([i(t),n])},d.addSingularRule=function(e,n){t.push([i(e),n])},d.addUncountableRule=function(e){"string"!=typeof e?(d.addPluralRule(e,"$0"),d.addSingularRule(e,"$0")):n[e.toLowerCase()]=!0},d.addIrregularRule=function(e,t){t=t.toLowerCase(),e=e.toLowerCase(),o[e]=t,r[t]=e},[["I","we"],["me","us"],["he","they"],["she","they"],["them","them"],["myself","ourselves"],["yourself","yourselves"],["itself","themselves"],["herself","themselves"],["himself","themselves"],["themself","themselves"],["is","are"],["was","were"],["has","have"],["this","these"],["that","those"],["echo","echoes"],["dingo","dingoes"],["volcano","volcanoes"],["tornado","tornadoes"],["torpedo","torpedoes"],["genus","genera"],["viscus","viscera"],["stigma","stigmata"],["stoma","stomata"],["dogma","dogmata"],["lemma","lemmata"],["schema","schemata"],["anathema","anathemata"],["ox","oxen"],["axe","axes"],["die","dice"],["yes","yeses"],["foot","feet"],["eave","eaves"],["goose","geese"],["tooth","teeth"],["quiz","quizzes"],["human","humans"],["proof","proofs"],["carve","carves"],["valve","valves"],["looey","looies"],["thief","thieves"],["groove","grooves"],["pickaxe","pickaxes"],["passerby","passersby"]].forEach((function(e){return d.addIrregularRule(e[0],e[1])})),[[/s?$/i,"s"],[/[^\u0000-\u007F]$/i,"$0"],[/([^aeiou]ese)$/i,"$1"],[/(ax|test)is$/i,"$1es"],[/(alias|[^aou]us|t[lm]as|gas|ris)$/i,"$1es"],[/(e[mn]u)s?$/i,"$1s"],[/([^l]ias|[aeiou]las|[ejzr]as|[iu]am)$/i,"$1"],[/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,"$1i"],[/(alumn|alg|vertebr)(?:a|ae)$/i,"$1ae"],[/(seraph|cherub)(?:im)?$/i,"$1im"],[/(her|at|gr)o$/i,"$1oes"],[/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i,"$1a"],[/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i,"$1a"],[/sis$/i,"ses"],[/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i,"$1$2ves"],[/([^aeiouy]|qu)y$/i,"$1ies"],[/([^ch][ieo][ln])ey$/i,"$1ies"],[/(x|ch|ss|sh|zz)$/i,"$1es"],[/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i,"$1ices"],[/\b((?:tit)?m|l)(?:ice|ouse)$/i,"$1ice"],[/(pe)(?:rson|ople)$/i,"$1ople"],[/(child)(?:ren)?$/i,"$1ren"],[/eaux$/i,"$0"],[/m[ae]n$/i,"men"],["thou","you"]].forEach((function(e){return d.addPluralRule(e[0],e[1])})),[[/s$/i,""],[/(ss)$/i,"$1"],[/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i,"$1fe"],[/(ar|(?:wo|[ae])l|[eo][ao])ves$/i,"$1f"],[/ies$/i,"y"],[/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i,"$1ie"],[/\b(mon|smil)ies$/i,"$1ey"],[/\b((?:tit)?m|l)ice$/i,"$1ouse"],[/(seraph|cherub)im$/i,"$1"],[/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i,"$1"],[/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i,"$1sis"],[/(movie|twelve|abuse|e[mn]u)s$/i,"$1"],[/(test)(?:is|es)$/i,"$1is"],[/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,"$1us"],[/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i,"$1um"],[/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i,"$1on"],[/(alumn|alg|vertebr)ae$/i,"$1a"],[/(cod|mur|sil|vert|ind)ices$/i,"$1ex"],[/(matr|append)ices$/i,"$1ix"],[/(pe)(rson|ople)$/i,"$1rson"],[/(child)ren$/i,"$1"],[/(eau)x?$/i,"$1"],[/men$/i,"man"]].forEach((function(e){return d.addSingularRule(e[0],e[1])})),["adulthood","advice","agenda","aid","aircraft","alcohol","ammo","analytics","anime","athletics","audio","bison","blood","bream","buffalo","butter","carp","cash","chassis","chess","clothing","cod","commerce","cooperation","corps","debris","diabetes","digestion","elk","energy","equipment","excretion","expertise","firmware","flounder","fun","gallows","garbage","graffiti","hardware","headquarters","health","herpes","highjinks","homework","housework","information","jeans","justice","kudos","labour","literature","machinery","mackerel","mail","media","mews","moose","music","mud","manga","news","only","personnel","pike","plankton","pliers","police","pollution","premises","rain","research","rice","salmon","scissors","series","sewage","shambles","shrimp","software","species","staff","swine","tennis","traffic","transportation","trout","tuna","wealth","welfare","whiting","wildebeest","wildlife","you",/pok[eé]mon$/i,/[^aeiou]ese$/i,/deer$/i,/fish$/i,/measles$/i,/o[iu]s$/i,/pox$/i,/sheep$/i].forEach(d.addUncountableRule),d}));var Qe=Ye(Ge.exports),Xe=function(e){var t={};try{t.WeakMap=WeakMap}catch(u){t.WeakMap=function(e,t){var n=t.defineProperty,r=t.hasOwnProperty,o=i.prototype;return o.delete=function(e){return this.has(e)&&delete e[this._]},o.get=function(e){return this.has(e)?e[this._]:void 0},o.has=function(e){return r.call(e,this._)},o.set=function(e,t){return n(e,this._,{configurable:!0,value:t}),this},i;function i(t){n(this,"_",{value:"_@ungap/weakmap"+e++}),t&&t.forEach(s,this)}function s(e){this.set(e[0],e[1])}}(Math.random(),Object)}var n=t.WeakMap,r={};try{r.WeakSet=WeakSet}catch(u){!function(e,t){var n=o.prototype;function o(){t(this,"_",{value:"_@ungap/weakmap"+e++})}n.add=function(e){return this.has(e)||t(e,this._,{value:!0,configurable:!0}),this},n.has=function(e){return this.hasOwnProperty.call(e,this._)},n.delete=function(e){return this.has(e)&&delete e[this._]},r.WeakSet=o}(Math.random(),Object.defineProperty)}function o(e,t,n,r,o,i){for(var s=("selectedIndex"in t),a=s;r>>0;ns;)--c;l=a+r-c;var w=Array(l),y=u[c];for(--n;y;){for(var v=y.newi,$=y.oldi;v"+e+"",r.querySelectorAll(t)):(r.innerHTML=e,r.childNodes)),n},function(e,t){return("svg"===t?function(e){var t=z(C),n=z("div");return n.innerHTML=''+e+"",O(t,n.firstChild.childNodes),t}:L)(e)});function O(e,t){for(var n=t.length;n--;)e.appendChild(t[0])}function z(e){return e===C?E.createDocumentFragment():E.createElementNS("http://www.w3.org/1999/xhtml",e)}var M,q,U,F,B,H,W,V,Z,Y=(q="appendChild",U="cloneNode",F="createTextNode",H=(B="importNode")in(M=e),(W=M.createDocumentFragment())[q](M[F]("g")),W[q](M[F]("")),(H?M[B](W,!0):W[U](!0)).childNodes.length<2?function e(t,n){for(var r=t[U](),o=t.childNodes||[],i=o.length,s=0;n&&s

    ',V.content.childNodes[0].getAttribute(Z)==G)||(G="_dt: "+G.slice(1,-1)+";",Q=!0)}catch(u){}var X="\x3c!--"+G+"--\x3e",J=8,ee=1,te=3,ne=/^(?:style|textarea)$/i,re=/^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i,oe=" \\f\\n\\r\\t",ie="[^"+oe+"\\/>\"'=]+",se="["+oe+"]+"+ie,ae="<([A-Za-z]+[A-Za-z0-9:._-]*)((?:",ce="(?:\\s*=\\s*(?:'[^']*?'|\"[^\"]*?\"|<[^>]*?>|"+ie.replace("\\/","")+"))?)",le=new RegExp(ae+se+ce+"+)(["+oe+"]*/?>)","g"),ue=new RegExp(ae+se+ce+"*)(["+oe+"]*/>)","g"),de=new RegExp("("+se+"\\s*=\\s*)(['\"]?)"+X+"\\2","gi");function pe(e,t,n,r){return"<"+t+n.replace(de,fe)+r}function fe(e,t,n){return t+(n||'"')+G+(n||'"')}function he(e,t,n){return re.test(t)?e:"<"+t+n+">"}var me=Q?function(e,t){var n=t.join(" ");return t.slice.call(e,0).sort((function(e,t){return n.indexOf(e.name)<=n.indexOf(t.name)?-1:1}))}:function(e,t){return t.slice.call(e,0)};function ge(t,n,r,o){for(var i=t.childNodes,s=i.length,a=0;a{e.remove()}))}function dt(e,t="long"){const n=new Intl.ListFormat(l,{style:t,type:e});return(e,t)=>{let r=0;return n.formatToParts(e).map((({type:n,value:o})=>"element"===n&&t?t(o,r++,e):o))}}const pt=dt("conjunction"),ft=dt("disjunction");function ht(e,t){return pt(e,t).join("")}function mt(e,t){return ft(e,t).join("")}function gt(e){return e.replace(/&/g,"&").replace(/>/g,">").replace(/"/g,""").replace(/new Date)return i}catch(e){console.error("Failed to use Cache API.",e)}const s=await fetch(n);if(!s.ok&&i)return console.warn(`Returning a stale cached response for ${r}`),i;if(o&&s.ok){const e=s.clone(),r=new Headers(s.headers),i=new Date(Date.now()+t);r.set("Expires",i.toISOString());const a=new Response(await e.blob(),{headers:r});await o.put(n,a).catch(console.error)}return s}function xt(e,t=(e=>e)){const n=e.map(t),r=n.slice(0,-1).map((e=>Je`${e}, `));return Je`${r}${n[n.length-1]}`}function kt(e,t){return[].concat(pt(e,t)).map((e=>"string"==typeof e?Je`${e}`:e))}function _t(e,t="",n="",r=!1){if(e.id)return e.id;n||(n=(e.title?e.title:e.textContent).trim());let o=r?n:n.toLowerCase();if(o=o.trim().normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/\W+/gim,"-").replace(/^-+/,"").replace(/-+$/,""),o?!/\.$/.test(o)&&/^[a-z]/i.test(t||o)||(o=`x${o}`):o="generatedID",t&&(o=`${t}-${o}`),e.ownerDocument.getElementById(o)){let t=0,n=`${o}-${t}`;for(;e.ownerDocument.getElementById(n);)t+=1,n=`${o}-${t}`;o=n}return e.id=o,o}function Et(e){const t=new Set,n="ltNodefault"in e.dataset?"":bt(e.textContent),r=e.children[0];if(e.dataset.lt?e.dataset.lt.split("|").map((e=>bt(e))).forEach((e=>t.add(e))):1===e.childNodes.length&&1===e.getElementsByTagName("abbr").length&&r.title?t.add(r.title):'""'===e.textContent&&t.add("the-empty-string"),t.add(n),t.delete(""),e.dataset.localLt){e.dataset.localLt.split("|").forEach((e=>t.add(bt(e))))}return[...t]}function Ct(e,t,n={copyAttributes:!0}){if(e.localName===t)return e;const r=e.ownerDocument.createElement(t);if(n.copyAttributes)for(const{name:t,value:n}of e.attributes)r.setAttribute(t,n);return r.append(...e.childNodes),e.replaceWith(r),r}function St(e,t){const n=t.closest(ct);let r=!1;if(n&&(r=!t.closest(".normative")||!n.querySelector(".normative")),e.startsWith("!")){if(r)return{type:"informative",illegal:!0};r=!1}else e.startsWith("?")&&(r=!0);return{type:r?"informative":"normative",illegal:!1}}function Lt(e,t){return t.append(...e.childNodes),e.appendChild(t),e}function Rt(e,t){const n=[];let r=e.parentElement;for(;r;){const e=r.closest(t);if(!e)break;n.push(e),r=e.parentElement}return n}function At(e){const{previousSibling:t}=e;if(!t||t.nodeType!==Node.TEXT_NODE)return"";const n=t.textContent.lastIndexOf("\n");if(-1===n)return"";const r=t.textContent.slice(n+1);return/\S/.test(r)?"":r}class Tt extends Set{constructor(e=[]){super();for(const t of e)this.add(t)}add(e){return this.has(e)||this.getCanonicalKey(e)?this:super.add(e)}has(e){return super.has(e)||[...this.keys()].some((t=>t.toLowerCase()===e.toLowerCase()))}delete(e){return super.has(e)?super.delete(e):super.delete(this.getCanonicalKey(e))}getCanonicalKey(e){return super.has(e)?e:[...this.keys()].find((t=>t.toLowerCase()===e.toLowerCase()))}}function Pt(e){const t=e.cloneNode(!0);return t.querySelectorAll("[id]").forEach((e=>e.removeAttribute("id"))),t.querySelectorAll("dfn").forEach((e=>{Ct(e,"span",{copyAttributes:!1})})),t.hasAttribute("id")&&t.removeAttribute("id"),It(t),t}function It(e){const t=document.createTreeWalker(e,NodeFilter.SHOW_COMMENT);for(const e of[...Dt(t)])e.remove()}function*Dt(e){for(;e.nextNode();)yield e.currentNode}class Nt extends Map{constructor(e=[]){return super(),e.forEach((([e,t])=>{this.set(e,t)})),this}set(e,t){return super.set(e.toLowerCase(),t),this}get(e){return super.get(e.toLowerCase())}has(e){return super.has(e.toLowerCase())}delete(e){return super.delete(e.toLowerCase())}}class jt extends Error{constructor(e,t,n){super(e);const r=n.isWarning?"ReSpecWarning":"ReSpecError";Object.assign(this,{message:e,plugin:t,name:r,...n}),n.elements&&n.elements.forEach((t=>function(e,t,n){e.classList.add("respec-offending-element"),e.hasAttribute("title")||e.setAttribute("title",n||t),e.id||_t(e,"respec-offender")}(t,e,n.title)))}toJSON(){const{message:e,name:t,stack:n}=this,{plugin:r,hint:o,elements:i,title:s,details:a}=this;return{message:e,name:t,plugin:r,hint:o,elements:i,title:s,details:a,stack:n}}}function Ot(e,t,n={}){const r={...n,isWarning:!1};o("error",new jt(e,t,r))}function zt(e,t,n={}){const r={...n,isWarning:!0};o("warn",new jt(e,t,r))}function Mt(e){return{showError:(t,n)=>Ot(t,e,n),showWarning:(t,n)=>zt(t,e,n)}}function qt(e){return e?`\`${e}\``:""}function Ut(e,{quotes:t}={quotes:!1}){return mt(e,t?e=>{return qt((t=e,String(t)?`"${t}"`:""));var t}:qt)}function Ft(e,...t){return Bt(e.map(((e,n)=>{const r=t[n];if(!r)return e;if(!r.startsWith("[")&&!r.endsWith("]"))return e+r;const[o,i]=r.slice(1,-1).split("|");if(i){return`${e}[${o}](${new URL(i,"https://respec.org/docs/")})`}return`${e}[\`${o}\`](https://respec.org/docs/#${o})`})).join(""))}function Bt(e){if(!e)return e;const t=e.trimEnd().split("\n");for(;t.length&&!t[0].trim();)t.shift();const n=t.filter((e=>e.trim())).map((e=>e.search(/[^\s]/))),r=Math.min(...n);return t.map((e=>e.slice(r))).join("\n")}const Ht=new Map([["text/html","html"],["application/xml","xml"]]);function Wt(e,t=document){const n=Ht.get(e);if(!n){const t=[...Ht.values()].join(", ");throw new TypeError(`Invalid format: ${e}. Expected one of: ${t}.`)}const r=Vt(n,t);return`data:${e};charset=utf-8,${encodeURIComponent(r)}`}function Vt(e,t){const n=t.cloneNode(!0);!function(e){const{head:t,body:n,documentElement:r}=e;It(e),e.querySelectorAll(".removeOnSave, #toc-nav").forEach((e=>e.remove())),n.classList.remove("toc-sidebar"),ut(r);const i=e.createDocumentFragment(),s=e.querySelector("meta[name='viewport']");s&&t.firstChild!==s&&i.appendChild(s);let a=e.querySelector("meta[charset], meta[content*='charset=']");a||(a=Je``);i.appendChild(a);const c=`ReSpec ${window.respecVersion||"Developer Channel"}`,l=Je` + + `;i.appendChild(l),t.prepend(i),o("beforesave",r)}(n);let r="";if("xml"===e)r=(new XMLSerializer).serializeToString(n);else!function(e){e.querySelectorAll("style").forEach((e=>{e.innerHTML=`\n${e.innerHTML}\n`})),e.querySelectorAll("head > *").forEach((e=>{e.outerHTML=`\n${e.outerHTML}`}))}(n),n.doctype&&(r+=(new XMLSerializer).serializeToString(n.doctype)),r+=n.documentElement.outerHTML;return r}n("core/exporter",{rsDocToDataURL:Wt});class Zt{constructor(){this._respecDonePromise=new Promise((e=>{i("end-all",(()=>e()),{once:!0})})),this.errors=[],this.warnings=[],i("error",(e=>{console.error(e,e.toJSON()),this.errors.push(e)})),i("warn",(e=>{console.warn(e,e.toJSON()),this.warnings.push(e)}))}get version(){return window.respecVersion}get ready(){return this._respecDonePromise}async toHTML(){return Vt("html",document)}}const Yt="core/post-process";const Kt="core/pre-process";const Gt="core/base-runner";async function Qt(e){!function(){const e=new Zt;Object.defineProperty(document,"respec",{value:e})}(),o("start-all",respecConfig),function(e){const t={},n=e=>Object.assign(t,e);n(e),i("amend-user-config",n),i("end-all",(()=>{const e=document.createElement("script");e.id="initialUserConfig",e.type="application/json";for(const e of s)e in t&&delete t[e];e.innerHTML=JSON.stringify(t,null,2),document.head.appendChild(e)}))}(respecConfig),function(e){const t=new URLSearchParams(document.location.search),n=Array.from(t).filter((([e,t])=>!!e&&!!t)).map((([e,t])=>{const n=decodeURIComponent(e),r=decodeURIComponent(t.replace(/%3D/g,"="));let o;try{o=JSON.parse(r)}catch{o=r}return[n,o]})),r=Object.fromEntries(n);Object.assign(e,r),o("amend-user-config",r)}(respecConfig),performance.mark(`${Gt}-start`),await async function(e){if(Array.isArray(e.preProcess)){const t=e.preProcess.filter((e=>{const t="function"==typeof e;return t||Ot("Every item in `preProcess` must be a JS function.",Kt),t})).map((async(t,n)=>{const r=Mt(`${Kt}/${t.name||`[${n}]`}`);try{return await t(e,document,r)}catch(e){Ot(`Function ${t.name} threw an error during \`preProcess\`.`,Kt,{hint:"See developer console."}),console.error(e)}}));await Promise.all(t)}}(respecConfig);const t=e.filter((e=>{return(t=e)&&(t.run||t.Plugin);var t}));t.forEach((e=>!e.name&&console.warn("Plugin lacks name:",e))),await async function(e,t){for(const n of e.filter((e=>e.prepare)))try{await n.prepare(t)}catch(e){console.error(e)}}(t,respecConfig),await async function(e,t){for(const n of e){const e=n.name||"";try{await new Promise((async(r,o)=>{const i=setTimeout((()=>{const t=`Plugin ${e} took too long.`;console.error(t,n),o(new Error(t))}),15e3);performance.mark(`${e}-start`);try{n.Plugin?(await new n.Plugin(t).run(),r()):n.run&&(await n.run(t),r())}catch(e){o(e)}finally{clearTimeout(i),performance.mark(`${e}-end`),performance.measure(e,`${e}-start`,`${e}-end`)}}))}catch(e){console.error(e)}}}(t,respecConfig),o("plugins-done",respecConfig),await async function(e){if(Array.isArray(e.postProcess)){const t=e.postProcess.filter((e=>{const t="function"==typeof e;return t||Ot("Every item in `postProcess` must be a JS function.",Yt),t})).map((async(t,n)=>{const r=Mt(`${Yt}/${t.name||`[${n}]`}`);try{return await t(e,document,r)}catch(e){Ot(`Function ${t.name} threw an error during \`postProcess\`.`,Yt,{hint:"See developer console."}),console.error(e)}}));await Promise.all(t)}"function"==typeof e.afterEnd&&await e.afterEnd(e,document)}(respecConfig),o("end-all"),ut(document),performance.mark(`${Gt}-end`),performance.measure(Gt,`${Gt}-start`,`${Gt}-end`)}var Xt=Object.freeze({__proto__:null,name:Gt,runAll:Qt});var Jt=String.raw`.respec-modal .close-button{position:absolute;z-index:inherit;padding:.2em;font-weight:700;cursor:pointer;margin-left:5px;border:none;background:0 0} +#respec-ui{position:fixed;display:flex;flex-direction:row-reverse;top:20px;right:20px;width:202px;text-align:right;z-index:9000} +#respec-pill,.respec-info-button{height:2.4em;background:#fff;background:var(--bg,#fff);color:#787878;color:var(--tocnav-normal-text,#787878);border:1px solid #ccc;box-shadow:1px 1px 8px 0 rgba(100,100,100,.5);box-shadow:1px 1px 8px 0 var(--tocsidebar-shadow,rgba(100,100,100,.5));padding:.2em 0} +.respec-info-button{border:none;opacity:.75;border-radius:2em;margin-right:1em;min-width:3.5em;will-change:opacity} +.respec-info-button:focus,.respec-info-button:hover{opacity:1;transition:opacity .2s} +#respec-pill{width:4.8em} +#respec-pill:not(:disabled){animation:respec-fadein .6s ease-in-out} +@keyframes respec-fadein{ +from{margin-top:-1.2em;border-radius:50%;border:.2em solid rgba(100,100,100,.5);box-shadow:none;height:4.8em} +to{margin-top:0;border:1px solid #ccc;border-radius:0;box-shadow:1px 1px 8px 0 rgba(100,100,100,.5);height:2.4em} +} +#respec-pill:disabled{margin-top:-1.2em;position:relative;border:none;box-shadow:none;border-radius:50%;width:4.8em;height:4.8em;padding:0} +#respec-pill:disabled::after{position:absolute;content:'';inset:-.2em;border-radius:50%;border:.2em solid rgba(100,100,100,.5);border-left:.2em solid transparent;animation:respec-spin .5s infinite linear} +@media (prefers-reduced-motion){ +#respec-pill:not(:disabled){animation:none} +#respec-pill:disabled::after{animation:none;border-left:.2em solid rgba(100,100,100,.5)} +} +@keyframes respec-spin{ +0%{transform:rotate(0)} +100%{transform:rotate(360deg)} +} +.respec-hidden{visibility:hidden;opacity:0;transition:visibility 0s .2s,opacity .2s linear} +.respec-visible{visibility:visible;opacity:1;transition:opacity .2s linear} +#respec-pill:focus,#respec-pill:hover{color:#000;background-color:#f5f5f5;transition:color .2s} +#respec-menu{position:absolute;margin:0;padding:0;font-family:sans-serif;background:var(--bg,#fff);color:var(--text,#000);box-shadow:1px 1px 8px 0 rgba(100,100,100,.5);width:200px;display:none;text-align:left;margin-top:32px;font-size:.8em} +#respec-menu:not([hidden]){display:block} +#respec-menu li{list-style-type:none;margin:0;padding:0} +.respec-save-buttons{display:grid;grid-template-columns:repeat(auto-fill,minmax(47%,2fr));grid-gap:.5cm;padding:.5cm} +.respec-save-button:link{padding-top:16px;color:var(--def-text,#fff);background:var(--def-bg,#2a5aa8);justify-self:stretch;height:1cm;text-decoration:none;text-align:center;font-size:inherit;border:none;border-radius:.2cm} +.respec-save-button:link:hover{color:var(--def-text,#fff);background:var(--defrow-border,#2a5aa8);padding:0;margin:0;border:0;padding-top:16px} +.respec-save-button:link:focus{background:var(--tocnav-active-bg,#193766);color:var(--tocnav-active-text,#000)} +#respec-pill:focus,#respec-ui button:focus,.respec-option:focus{outline:0;outline-style:none} +#respec-pill-error{background-color:red;color:#fff} +#respec-pill-warning{background-color:orange;color:#fff} +.respec-error-list,.respec-warning-list{margin:0;padding:0;font-family:sans-serif;font-size:.85em} +.respec-warning-list{background-color:#fffbe6} +:is(.respec-warning-list,.respec-error-list)>li{list-style-type:none;margin:0;padding:.5em 0;padding-left:2em;padding-right:.5em} +:is(.respec-warning-list,.respec-error-list)>li+li{margin-top:.5rem} +:is(.respec-warning-list,.respec-error-list)>li:before{position:absolute;left:.4em} +:is(.respec-warning-list,.respec-error-list) p{padding:0;margin:0} +.respec-warning-list>li{color:#5c3b00;border-bottom:thin solid #fff5c2} +.respec-error-list,.respec-error-list li{background-color:#fff0f0} +.respec-warning-list>li::before{content:"⚠️"} +.respec-error-list>li::before{content:"💥"} +.respec-error-list>li{color:#5c3b00;border-bottom:thin solid #ffd7d7} +:is(.respec-warning-list,.respec-error-list)>li li{list-style:disc} +#respec-overlay{display:block;position:fixed;z-index:10000;top:0;left:0;height:100%;width:100%;background:#000} +.respec-show-overlay{transition:opacity .2s linear;opacity:.5} +.respec-hide-overlay{transition:opacity .2s linear;opacity:0} +.respec-modal{display:block;position:fixed;z-index:11000;top:10%;background:var(--bg,#fff);color:var(--text,#000);border:5px solid #666;border-color:var(--tocsidebar-shadow,#666);min-width:20%;padding:0;max-height:80%;overflow-y:auto;margin:0 -.5cm;left:20%;max-width:75%;min-width:60%} +.respec-modal h3{margin:0;padding:.2em;left:0!important;text-align:center;background:var(--tocsidebar-shadow,#ddd);color:var(--text,#000);font-size:1em} +#respec-menu button.respec-option{background:var(--bg,#fff);color:var(--text,#000);border:none;width:100%;text-align:left;font-size:inherit;padding:1.2em 1.2em} +#respec-menu button.respec-option:hover{background-color:var(--tocnav-hover-bg,#eee);color:var(--tocnav-hover-text,#000)} +.respec-cmd-icon{padding-right:.5em} +#respec-ui button.respec-option:first-child{margin-top:0} +#respec-ui button.respec-option:last-child{border:none;border-radius:inherit;margin-bottom:0} +.respec-button-copy-paste{position:absolute;height:28px;width:40px;cursor:pointer;background-image:linear-gradient(#fcfcfc,#eee);border:1px solid #90b8de;border-left:0;border-radius:0 0 3px 0;-webkit-user-select:none;user-select:none;-webkit-appearance:none;top:0;left:127px} +@media print{ +#respec-ui{display:none} +} +.respec-iframe{width:100%;min-height:550px;height:100%;overflow:hidden;padding:0;margin:0;border:0} +.respec-iframe:not(.ready){background:url(https://respec.org/xref/loader.gif) no-repeat center} +.respec-iframe+a[href]{font-size:.9rem;float:right;margin:0 .5em .5em;border-bottom-width:1px} +p:is(.respec-hint,.respec-occurrences){display:block;margin-top:.5em} +.respec-plugin{text-align:right;color:rgb(120,120,120,.5);font-size:.6em}`;const en=/>/gm,tn=/&/gm;class nn extends tt.Renderer{code(e,t,n){const{language:r,...o}=nn.parseInfoString(t);if(/(^webidl$)/i.test(r))return`
    ${e}
    `;const i=super.code(e,r,n).replace('class="language-','class="'),{example:s,illegalExample:a}=o;if(!s&&!a)return i;const c=s||a,l=`${r} ${s?"example":"illegal-example"}`;return i.replace("
    ",`
    `)}image(e,t,n){if(!t)return super.image(e,t,n);return String.raw`
    +      
    + ${n} +
    ${t}
    +
    + `}static parseInfoString(e){const t=e.search(/\s/);if(-1===t)return{language:e};const n=e.slice(0,t),r=e.slice(t+1);let o;if(r)try{o=JSON.parse(`{ ${r} }`)}catch(e){console.error(e)}return{language:n,...o}}heading(e,t,n){const r=/(.+)\s+{#([\w-]+)}$/;if(r.test(e)){const[,n,o]=e.match(r);return`${n}`}return super.heading(e,t,n)}}const rn={gfm:!0,renderer:new nn};function on(e,t={inline:!1}){const n=Bt(e).replace(en,">").replace(tn,"&");return t.inline?tt.parseInline(n,rn):tt.parse(n,rn)}function sn(e){for(const t of e.getElementsByTagName("pre"))t.prepend("\n");e.innerHTML=on(e.innerHTML)}const an=(cn="[data-format='markdown']:not(body)",e=>{const t=e.querySelectorAll(cn);return t.forEach(sn),Array.from(t)});var cn;var ln=Object.freeze({__proto__:null,markdownToHtml:on,name:"core/markdown",run:function(e){const t=!!document.querySelector("[data-format=markdown]:not(body)"),n="markdown"===e.format;if(!n&&!t)return;if(!n)return void an(document.body);const r=document.getElementById("respec-ui");r.remove();const o=document.body.cloneNode(!0);!function(e,t){const n=e.querySelectorAll(t);for(const e of n){const{innerHTML:t}=e;if(/^<\w/.test(t.trimStart()))continue;const n=t.split("\n"),r=n.slice(0,2).join("\n"),o=n.slice(-2).join("\n");if(r.trim()&&e.prepend("\n\n"),o.trim()){const t=At(e);e.append(`\n\n${t}`)}}}(o,"[data-format=markdown], section, div, address, article, aside, figure, header, main"),sn(o),function(e){Array.from(e).forEach((e=>{e.replaceWith(e.textContent)}))}(o.querySelectorAll(".nolinks a[href]")),o.append(r),document.body.replaceWith(o)}});function un(e,t){e&&Array.from(t).forEach((([t,n])=>{e.setAttribute(`aria-${t}`,n)}))}!function(){const e=document.createElement("style");e.id="respec-ui-styles",e.textContent=Jt,e.classList.add("removeOnSave"),document.head.appendChild(e)}();const dn=Je``,pn=Je``,fn=Je``;let hn,mn;window.addEventListener("load",(()=>$n(pn)));const gn=[],bn=[],wn={};i("start-all",(()=>document.body.prepend(dn)),{once:!0}),i("end-all",(()=>document.body.prepend(dn)),{once:!0});const yn=Je``;function vn(){pn.classList.toggle("respec-hidden"),pn.classList.toggle("respec-visible"),pn.hidden=!pn.hidden}function $n(e){const t=e.querySelectorAll("a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled])"),n=t[0],r=t[t.length-1];n&&n.focus(),e.addEventListener("keydown",(e=>{"Tab"===e.key&&(e.shiftKey?document.activeElement===n&&(r.focus(),e.preventDefault()):document.activeElement===r&&(n.focus(),e.preventDefault()))}))}dn.appendChild(yn),yn.addEventListener("click",(e=>{e.stopPropagation(),yn.setAttribute("aria-expanded",String(pn.hidden)),vn(),pn.querySelector("li:first-child button").focus()})),document.documentElement.addEventListener("click",(()=>{pn.hidden||vn()})),dn.appendChild(pn),pn.addEventListener("keydown",(e=>{"Escape"!==e.key||pn.hidden||(yn.setAttribute("aria-expanded",String(pn.hidden)),vn(),yn.focus())}));const xn=new Map([["controls","respec-menu"],["expanded","false"],["haspopup","true"],["label","ReSpec Menu"]]);function kn(e,t,n,r){t.push(e),wn.hasOwnProperty(n)||(wn[n]=function(e,t,n){const r=`respec-pill-${e}`,o=Je``;o.addEventListener("click",(()=>{o.setAttribute("aria-expanded","true");const r=Je`
      `;for(const e of t){const t=document.createRange().createContextualFragment(En(e)),n=document.createElement("li");t.firstElementChild===t.lastElementChild?n.append(...t.firstElementChild.childNodes):n.appendChild(t),r.appendChild(n)}_n.freshModal(n,r,o)}));const i=new Map([["expanded","false"],["haspopup","true"],["controls",`respec-pill-${e}-modal`]]);return un(o,i),o}(n,t,r),dn.appendChild(wn[n]));const o=wn[n];o.textContent=t.length;const i=1===t.length?rt.singular(r):r;un(o,new Map([["label",`${t.length} ${i}`]]))}un(yn,xn);const _n={show(){try{dn.hidden=!1}catch(e){console.error(e)}},hide(){dn.hidden=!0},enable(){yn.removeAttribute("disabled")},addCommand(e,t,n,r){r=r||"";const o=`respec-button-${e.toLowerCase().replace(/\s+/,"-")}`,i=Je``,s=Je`
    1. ${i}
    2. `;return s.addEventListener("click",t),pn.appendChild(s),i},error(e){kn(e,gn,"error","ReSpec Errors")},warning(e){kn(e,bn,"warning","ReSpec Warnings")},closeModal(e){mn&&(mn.classList.remove("respec-show-overlay"),mn.classList.add("respec-hide-overlay"),mn.addEventListener("transitionend",(()=>{mn.remove(),mn=null}))),e&&e.setAttribute("aria-expanded","false"),hn&&(hn.remove(),hn=null,yn.focus())},freshModal(e,t,n){hn&&hn.remove(),mn&&mn.remove(),mn=Je`
      `;const r=`${n.id}-modal`,o=`${r}-heading`;hn=Je``;const i=new Map([["labelledby",o]]);un(hn,i),document.body.append(mn,hn),mn.addEventListener("click",(()=>this.closeModal(n))),mn.classList.toggle("respec-show-overlay"),hn.hidden=!1,$n(hn)}};function En(e){if("string"==typeof e)return e;const t=e.plugin?`

      (plugin: "${e.plugin}")

      `:"",n=e.hint?`\n${on(`

      How to fix: ${Bt(e.hint)}`,{inline:!e.hint.includes("\n")})}\n`:"",r=Array.isArray(e.elements)?`

      Occurred ${e.elements.length} times at:

      \n ${on(e.elements.map(Cn).join("\n"))}`:"",o=e.details?`\n\n
      \n${e.details}\n
      \n`:"";return`${on(`**${gt(e.message)}**`,{inline:!0})}${n}${r}${o}${t}`}function Cn(e){return`* [\`<${e.localName}>\`](#${e.id}) element`}document.addEventListener("keydown",(e=>{"Escape"===e.key&&_n.closeModal()})),window.respecUI=_n,i("error",(e=>_n.error(e))),i("warn",(e=>_n.warning(e)));var Sn=Object.freeze({__proto__:null,name:"core/ui",ui:_n});async function Ln(e){try{_n.show(),await async function(){"loading"===document.readyState&&await new Promise((e=>document.addEventListener("DOMContentLoaded",e)))}(),await Qt(e)}finally{_n.enable()}}window.addEventListener("error",(e=>{console.error(e.error,e.message,e)}));const Rn=[Promise.resolve().then((function(){return Xt})),Promise.resolve().then((function(){return Sn})),Promise.resolve().then((function(){return An})),Promise.resolve().then((function(){return u})),Promise.resolve().then((function(){return In})),Promise.resolve().then((function(){return Mn})),Promise.resolve().then((function(){return Wn})),Promise.resolve().then((function(){return Qn})),Promise.resolve().then((function(){return ln})),Promise.resolve().then((function(){return Xn})),Promise.resolve().then((function(){return Jn})),Promise.resolve().then((function(){return nr})),Promise.resolve().then((function(){return ir})),Promise.resolve().then((function(){return lr})),Promise.resolve().then((function(){return fr})),Promise.resolve().then((function(){return Ir})),Promise.resolve().then((function(){return jr})),Promise.resolve().then((function(){return Or})),Promise.resolve().then((function(){return qr})),Promise.resolve().then((function(){return Go})),Promise.resolve().then((function(){return Jo})),Promise.resolve().then((function(){return li})),Promise.resolve().then((function(){return ui})),Promise.resolve().then((function(){return hi})),Promise.resolve().then((function(){return yi})),Promise.resolve().then((function(){return _i})),Promise.resolve().then((function(){return Si})),Promise.resolve().then((function(){return bo})),Promise.resolve().then((function(){return Zi})),Promise.resolve().then((function(){return cs})),Promise.resolve().then((function(){return Oi})),Promise.resolve().then((function(){return Lo})),Promise.resolve().then((function(){return $s})),Promise.resolve().then((function(){return ks})),Promise.resolve().then((function(){return _s})),Promise.resolve().then((function(){return Ps})),Promise.resolve().then((function(){return Ds})),Promise.resolve().then((function(){return Os})),Promise.resolve().then((function(){return Us})),Promise.resolve().then((function(){return Ws})),Promise.resolve().then((function(){return Ks})),Promise.resolve().then((function(){return ta})),Promise.resolve().then((function(){return na})),Promise.resolve().then((function(){return ca})),Promise.resolve().then((function(){return ma})),Promise.resolve().then((function(){return va})),Promise.resolve().then((function(){return Ca})),Promise.resolve().then((function(){return Ra})),Promise.resolve().then((function(){return Ta})),Promise.resolve().then((function(){return Ia})),Promise.resolve().then((function(){return Ua})),Promise.resolve().then((function(){return Va})),Promise.resolve().then((function(){return Za})),Promise.resolve().then((function(){return Ya})),Promise.resolve().then((function(){return Qa})),Promise.resolve().then((function(){return tc})),Promise.resolve().then((function(){return oc})),Promise.resolve().then((function(){return cc})),Promise.resolve().then((function(){return dc})),Promise.resolve().then((function(){return hc})),Promise.resolve().then((function(){return bc})),Promise.resolve().then((function(){return vc})),Promise.resolve().then((function(){return kc})),Promise.resolve().then((function(){return Sc}))];Promise.all(Rn).then((e=>Ln(e))).catch((e=>console.error(e)));var An=Object.freeze({__proto__:null,name:"core/location-hash",run:function(){window.location.hash&&document.respec.ready.then((()=>{let e=decodeURIComponent(window.location.hash).slice(1);const t=document.getElementById(e),n=/\W/.test(e);if(!t&&n){const t=e.replace(/[\W]+/gim,"-").replace(/^-+/,"").replace(/-+$/,"");document.getElementById(t)&&(e=t)}window.location.hash=`#${e}`}))}});var Tn=String.raw`@keyframes pop{ +0%{transform:scale(1,1)} +25%{transform:scale(1.25,1.25);opacity:.75} +100%{transform:scale(1,1)} +} +a.internalDFN{color:inherit;border-bottom:1px solid #99c;text-decoration:none} +a.externalDFN{color:inherit;border-bottom:1px dotted #ccc;text-decoration:none} +a.bibref{text-decoration:none} +.respec-offending-element:target{animation:pop .25s ease-in-out 0s 1} +.respec-offending-element,a[href].respec-offending-element{text-decoration:red wavy underline} +@supports not (text-decoration:red wavy underline){ +.respec-offending-element:not(pre){display:inline-block} +.respec-offending-element{background:url(data:image/gif;base64,R0lGODdhBAADAPEAANv///8AAP///wAAACwAAAAABAADAEACBZQjmIAFADs=) bottom repeat-x} +} +#references :target{background:#eaf3ff;animation:pop .4s ease-in-out 0s 1} +cite .bibref{font-style:normal} +a[href].orcid{padding-left:4px;padding-right:4px} +a[href].orcid>svg{margin-bottom:-2px} +ol.tof,ul.tof{list-style:none outside none} +.caption{margin-top:.5em;font-style:italic} +#issue-summary>ul{column-count:2} +#issue-summary li{list-style:none;display:inline-block} +details.respec-tests-details{margin-left:1em;display:inline-block;vertical-align:top} +details.respec-tests-details>*{padding-right:2em} +details.respec-tests-details[open]{z-index:999999;position:absolute;border:thin solid #cad3e2;border-radius:.3em;background-color:#fff;padding-bottom:.5em} +details.respec-tests-details[open]>summary{border-bottom:thin solid #cad3e2;padding-left:1em;margin-bottom:1em;line-height:2em} +details.respec-tests-details>ul{width:100%;margin-top:-.3em} +details.respec-tests-details>li{padding-left:1em} +.self-link:hover{opacity:1;text-decoration:none;background-color:transparent} +aside.example .marker>a.self-link{color:inherit} +.header-wrapper{display:flex;align-items:baseline;position:relative;left:-.5em} +:is(h2,h3,h4,h5,h6):not(#toch2)+a.self-link{color:inherit;order:-1;position:relative;left:-.7em;font-size:1rem;opacity:.5} +:is(h2,h3,h4,h5,h6)+a.self-link::before{content:"§";text-decoration:none;color:var(--heading-text)} +:is(h2,h3)+a.self-link{top:-.2em} +:is(h4,h5,h6)+a.self-link::before{color:#000} +@media (max-width:767px){ +dd{margin-left:0} +} +@media print{ +.removeOnSave{display:none} +}`;const Pn=function(){const e=document.createElement("style");return e.id="respec-mainstyle",e.textContent=Tn,document.head.appendChild(e),e}();var In=Object.freeze({__proto__:null,name:"core/style",run:function(e){e.noReSpecCSS&&Pn.remove()}});var Dn=String.raw`img.license{float:left;padding-right:5px}`;const Nn="logius/style";function jn(){const e=Je` + + + + + + + + + + + + + + + +
      + + + + + + + + + +
      +
      + + + + + + +
      + + + + + + + + jpg + png + + + UNRECOGNIZED MIMETYPE: {$mimetype} + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-common.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-common.xsl new file mode 100644 index 000000000..4a1be904e --- /dev/null +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-common.xsl @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-core-modes.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-core-modes.xsl new file mode 100644 index 000000000..1377bd55f --- /dev/null +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-core-modes.xsl @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-core-scanner.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-core-scanner.xsl new file mode 100644 index 000000000..52b351d6c --- /dev/null +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-core-scanner.xsl @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Geen MsWord bestand "{$doc-name}" aangetroffen. + + + + + + + + + + + + Dit document is al verwerkt: "{$doc-name}" + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-file-finalize.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-file-finalize.xsl new file mode 100644 index 000000000..524e22701 --- /dev/null +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-file-finalize.xsl @@ -0,0 +1,437 @@ + + + + + + + unknown-file-name + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Plaatje zonder bron, in: {(preceding::title)[1]} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deze noot bestaat niet: {$name} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Aantal kolommen in table: matrix specificatie en kolommen aangetroffen is niet hetzelfde + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + +
      +
      + + + + + + + + + + + + +
      + +
      +
      + + + +
      +
      + + +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type-name-here + default + + + + + + + + + + + + + + +
      \ No newline at end of file diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-file-prepare.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-file-prepare.xsl new file mode 100644 index 000000000..0714185ba --- /dev/null +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-file-prepare.xsl @@ -0,0 +1,321 @@ + + + + + + + + unknown-file-path + unknown-file-name + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + x?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <xsl:apply-templates mode="#current"/> + + + + + + + <xsl:value-of select=".//p[1]"/> + + + + + + + + + + + + + + + + <xsl:apply-templates mode="#current"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ^(\d+);\s*(FATAL|WARNING|ERROR|INFO);(.+?);\s*(.+?);\s*(.+)$ + ^(.+?):\s*(.+)$ + + + + + + + + + + + + + + + + + + + + + + + + Metadata formaat niet herkend: {$firstpar} + + + + + + + + + + + + ^(.+?)(:\s*(.+))?$ + + + + + + + + + + + + + + + + + + + + + + + + x?> + + + + Extension formaat niet herkend: {$ext} + + + + + + + + + + + + + + + + + + Invalid or unknown metadata key: {$following/@key} + + + + + + + + + ^(.+?):\s+(.+)$ + + + + {regex-group(1)}:{regex-group(2)} + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-mode-default.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-mode-default.xsl new file mode 100644 index 000000000..3bae83f10 --- /dev/null +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-mode-default.xsl @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-mode-primer.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-mode-primer.xsl new file mode 100644 index 000000000..61576b248 --- /dev/null +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-mode-primer.xsl @@ -0,0 +1,608 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Aggregatietype + Externe koppeling + Relatiesoort - Relatiesoort leidend + + + Alias + Attribuutsoort + Codelijst + Externe koppeling + Gegevensgroep + Gegevensgroeptype + Generalisatie Datatypes + Objecttype + Referentie element + Referentielijst + Relatieklasse + Relatierol - Relatierol leidend + Relatierol - Relatiesoort leidend + Relatiesoort - Relatierol leidend + Relatiesoort - Relatiesoort leidend + + + Authentiek + Attribuutsoort + Gegevensgroep + Relatierol - Relatierol leidend + Relatiesoort - Relatiesoort leidend + + + Begrip + Attribuutsoort + Codelijst + Data element + Enumeratie + Externe koppeling + Gegevensgroep + Gegevensgroeptype + Generalisatie Datatypes + Gestructureerd datatype + Keuze + Objecttype + Primitief datatype + Referentie element + Referentielijst + Relatieklasse + Relatierol - Relatierol leidend + Relatierol - Relatiesoort leidend + Relatiesoort - Relatierol leidend + Relatiesoort - Relatiesoort leidend + + + Code + Enumeratiewaarde + + + Datum opname + Attribuutsoort + Codelijst + Externe koppeling + Gegevensgroep + Gegevensgroeptype + Gestructureerd datatype + Keuze + Objecttype + Primitief datatype + Referentie element + Referentielijst + Relatierol - Relatierol leidend + Relatiesoort - Relatiesoort leidend + + + Definitie + Attribuutsoort + Codelijst + Data element + Enumeratie + Enumeratiewaarde + Extern + Gegevensgroep + Gegevensgroeptype + Gestructureerd datatype + Informatiemodel + Keuze + Objecttype + Primitief datatype + Referentie element + Referentielijst + Relatieklasse + Relatierol - Relatierol leidend + Relatierol - Relatiesoort leidend + Relatiesoort - Relatierol leidend + Relatiesoort - Relatiesoort leidend + View + + + Formeel patroon + Attribuutsoort + Data element + Gestructureerd datatype + Primitief datatype + Referentie element + + + Gegevensgroeptype + Gegevensgroep + + + Herkomst + Attribuutsoort + Codelijst + Extern + Gegevensgroep + Gestructureerd datatype + Informatiemodel + Keuze + Objecttype + Primitief datatype + Referentielijst + Relatierol - Relatierol leidend + Relatiesoort - Relatiesoort leidend + View + + + Herkomst definitie + Attribuutsoort + Gegevensgroep + Gegevensgroeptype + Objecttype + Relatierol - Relatierol leidend + Relatiesoort - Relatiesoort leidend + + + Identificerend + Attribuutsoort + Referentie element + + + Indicatie abstract object + Objecttype + + + Indicatie afleidbaar + Attribuutsoort + Relatiesoort - Relatiesoort leidend + + + Indicatie classificerend + Attribuutsoort + + + Indicatie formele historie + Attribuutsoort + Gegevensgroep + Relatierol - Relatierol leidend + Relatiesoort - Relatiesoort leidend + + + Indicatie materiële historie + Attribuutsoort + Gegevensgroep + Relatierol - Relatierol leidend + Relatiesoort - Relatiesoort leidend + + + Informatiedomein + Informatiemodel + + + Informatiemodel type + Informatiemodel + + + Kardinaliteit + Attribuutsoort + Data element + Gegevensgroep + Referentie element + Relatierol - Relatierol leidend + Relatiesoort - Relatiesoort leidend + + + Kwaliteit + Objecttype + + + Lengte + Attribuutsoort + Data element + Primitief datatype + Referentie element + + + Locatie + Codelijst + Extern + Referentielijst + View + + + MIM extensie + Informatiemodel + + + MIM taal + Informatiemodel + + + MIM versie + Informatiemodel + + + Mogelijk geen waarde + Attribuutsoort + Relatierol - Relatierol leidend + Relatiesoort - Relatiesoort leidend + + + Naam + Attribuutsoort + Codelijst + Constraint + Data element + Domein + Enumeratie + Enumeratiewaarde + Extern + Externe koppeling + Gegevensgroep + Gegevensgroeptype + Generalisatie Datatypes + Gestructureerd datatype + Informatiemodel + Keuze + Objecttype + Primitief datatype + Referentie element + Referentielijst + Relatieklasse + Relatierol - Relatierol leidend + Relatierol - Relatiesoort leidend + Relatiesoort - Relatierol leidend + Relatiesoort - Relatiesoort leidend + View + + + Patroon + Attribuutsoort + Data element + Gestructureerd datatype + Primitief datatype + Referentie element + + + Populatie + Objecttype + + + Relatie doel + Externe koppeling + Relatiesoort - Relatiesoort leidend + + + Relatie eigenaar + Externe koppeling + Relatiesoort - Relatiesoort leidend + + + Relatiemodelleringtype + Informatiemodel + + + Specificatie formeel + Constraint + + + Specificatie tekst + Constraint + + + Subtype + Generalisatie Datatypes + Generalisatie Objecttypes + + + Supertype + Generalisatie Datatypes + Generalisatie Objecttypes + + + Toelichting + Attribuutsoort + Codelijst + Gegevensgroep + Gegevensgroeptype + Objecttype + Referentie element + Referentielijst + Relatierol - Relatierol leidend + Relatiesoort - Relatiesoort leidend + + + Type + Attribuutsoort + Data element + Referentie element + + + Unidirectioneel + Externe koppeling + Relatiesoort - Relatiesoort leidend + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Geen bekende extensie: {@key} + + + + + + + + + + + + + + x?> + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-msword-fixes.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-msword-fixes.xsl new file mode 100644 index 000000000..9f6975b1d --- /dev/null +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-msword-fixes.xsl @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-respec-pack-process-catalog.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-respec-pack-process-catalog.xsl new file mode 100644 index 000000000..51fb74c03 --- /dev/null +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-respec-pack-process-catalog.xsl @@ -0,0 +1,102 @@ + + + + + + + + +
      + + + + + + + Cannot read catalog + + +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + {$src} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ERROR: UNKNOWN FILE EXTENSION: "{$fileext}" + + + + + + + +
      \ No newline at end of file diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-respec-xhtml-to-respec.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-respec-xhtml-to-respec.xsl new file mode 100644 index 000000000..6e1f5c8a7 --- /dev/null +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2documentor-respec-xhtml-to-respec.xsl @@ -0,0 +1,387 @@ + + + + + + + + + + + + + + + + + + + + + + + + {normalize-space(regex-group(1))} + + + + + + + + + + (Z?)(\+\d\d:\d\d) + \d\d\d\d-\d\d-\d\d + \d\d:\d\d:\d\d\.\d+ + ^{$regex-datef}({$regex-timezonef})?$ + ^{$regex-datef}T{$regex-timef}({$regex-timezonef})?$ + + + + + + + + + + + + + + + + + + + + + xhtml-to-respec + + + + +
      +

      Documentor rapport

      +

      Documentor heeft {count($errors)} fout(en) aangetroffen.

      +
      + + + + + + + +
      {@loc}{.}
      +

      Zoek hieronder naar:

      +
      FOUT! Melding
      +

      Verwerkt op

      +
      +
      +
      + + +
      +

      Documentor moet stoppen

      +

      Configuratie incompleet. Heeft jouw start-document bovenin een voldoende complete tabel met eigenschappen?

      +

      Het start-document is {$master-docx}.

      + +

      Eigenschappen voor zover bekend:

      + + + + + + + + +
      {substring-after(local-name(.),'prop-')}{.}
      +
      +
      + + + + + x?> + +
      +
      + + + + + +
      + + + + + + +
      + +
      +
      + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + +
      +                      
      +        
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ABBREV? {.} + + + + + + + + + + + + + + + + Catalogus ingelinkt: {$catalog-file-name} +
      + + + Catalogus ingevoegd: {$catalog-file-name} + + + + + + + + + + +
      + + + + + +
      +

      Lijst met afkortingen

      +
        + + +
      • {.} {@title}
      • +
        +
      +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {$norm-val} + + + XPARM? {$key} + + + + + + + + + + + + + TODO + + + + + + + + + + + + + + + + true + false + + + + + + + + + + + + + + + x?> + + + + + + + + + + + + +
      + FOUT! + {.} +
      +
      + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Armatiek-MIM-12-CONCEPTUAL-html-respec.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Armatiek-MIM-12-CONCEPTUAL-html-respec.xsl new file mode 100644 index 000000000..aa0152075 --- /dev/null +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Armatiek-MIM-12-CONCEPTUAL-html-respec.xsl @@ -0,0 +1,38 @@ + + + + + + + + + + + +

      + Deze tekst is normatief. + + imvertor + +

      +
      + + + + + + +
      \ No newline at end of file diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Armatiek-MIM-12-CONCEPTUAL.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Armatiek-MIM-12-CONCEPTUAL.xsl new file mode 100644 index 000000000..d00912e38 --- /dev/null +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Armatiek-MIM-12-CONCEPTUAL.xsl @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-BRO-MIM-11-CONCEPTUAL-html-msword.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-BRO-MIM-11-CONCEPTUAL-html-msword.xsl index 88e279931..fa544e983 100644 --- a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-BRO-MIM-11-CONCEPTUAL-html-msword.xsl +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-BRO-MIM-11-CONCEPTUAL-html-msword.xsl @@ -14,7 +14,7 @@ - + <xsl:value-of select="$subpath"/> diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-EIGENAAR-MIM-12-CONCEPTUAL-html-msword.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-EIGENAAR-MIM-12-CONCEPTUAL-html-msword.xsl index 44aeae28a..e9d9a103f 100644 --- a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-EIGENAAR-MIM-12-CONCEPTUAL-html-msword.xsl +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-EIGENAAR-MIM-12-CONCEPTUAL-html-msword.xsl @@ -14,7 +14,7 @@ <xsl:import href="common/Imvert2modeldoc-html-respec.xsl"/> <xsl:template match="/"> - <html> + <html lang="{$language}"> <head> <title> <xsl:value-of select="$subpath"/> diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-EIGENAAR-MIM-12-CONCEPTUAL-html-respec.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-EIGENAAR-MIM-12-CONCEPTUAL-html-respec.xsl index 793be0769..aa0152075 100644 --- a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-EIGENAAR-MIM-12-CONCEPTUAL-html-respec.xsl +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-EIGENAAR-MIM-12-CONCEPTUAL-html-respec.xsl @@ -1,5 +1,4 @@ -<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" - +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:imvert="http://www.imvertor.org/schema/system" @@ -7,64 +6,18 @@ xmlns:ext="http://www.imvertor.org/xsl/extensions" xmlns:imf="http://www.imvertor.org/xsl/functions" + xmlns:pack="http://www.armatiek.nl/functions/pack" + xmlns:dlogger="http://www.armatiek.nl/functions/dlogger-proxy" + exclude-result-prefixes="#all" - version="2.0"> + expand-text="yes"> - <xsl:import href="common/Imvert2modeldoc-html-respec.xsl"/> - <!-- this owner generates respec files with all info stored in that file. --> + <xsl:import href="common/Imvert2modeldoc-html-respec.xsl"/> <xsl:template match="/book"> - <html> - <head> - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> - <title> - <xsl:value-of select="concat('Catalogus: ',@name)"/> - - - - - -
      -

      - Samenvatting..... INSERT HERE -

      -
      -
      -

      - This documentation is updated at .... INSERT HERE -

      -
      -
      -

      Prologue

      -

      - Intro here........ -

      -
      - -
      -

      Epilogue

      -

      - Last remarks here........ -

      -
      - - +
      diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Geonovum-MIM-11-CONCEPTUAL-html-respec.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Geonovum-MIM-11-CONCEPTUAL-html-respec.xsl index 21df9ce17..f3bf03f67 100644 --- a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Geonovum-MIM-11-CONCEPTUAL-html-respec.xsl +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Geonovum-MIM-11-CONCEPTUAL-html-respec.xsl @@ -13,6 +13,9 @@ + + + diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-IHW-MIM-11-CONCEPTUAL-html-respec.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-IHW-MIM-11-CONCEPTUAL-html-respec.xsl index 733ff6a87..fbb9f4ea4 100644 --- a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-IHW-MIM-11-CONCEPTUAL-html-respec.xsl +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-IHW-MIM-11-CONCEPTUAL-html-respec.xsl @@ -13,54 +13,8 @@ - - - - - - - <xsl:value-of select="concat('Catalogus conceptueel model: ',@name)"/> - - - - - -
      -

      - Dit is een conceptueel model van IHW. -

      -
      -
      -

      - Deze documentatie van het conceptueel model is laatst bijgewerkt op . -

      -
      - - - +
      diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-KING-MBG-11-BSM-html-msword.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-KING-MBG-11-BSM-html-msword.xsl index 59089a9b0..3c8cf26df 100644 --- a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-KING-MBG-11-BSM-html-msword.xsl +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-KING-MBG-11-BSM-html-msword.xsl @@ -18,7 +18,7 @@ --> - + - - -
      -

      - Samenvatting conceptueel model..... INSERT HERE -

      -
      -
      -

      - Deze documentatie van het conceptueel model is laatst bijgewerkt op . -

      -
      -
      -

      Proloog

      -

      - Proloog conceptueel model hier. -

      -
      - -
      -

      Epiloog

      -

      - Epiloog conceptueel model hier. -

      -
      - - +
      diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Kadaster-html-msword.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Kadaster-html-msword.xsl index 761bf3080..d6a87e37a 100644 --- a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Kadaster-html-msword.xsl +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Kadaster-html-msword.xsl @@ -14,7 +14,7 @@ - + <xsl:value-of select="$subpath"/> diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Kadaster-html-respec.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Kadaster-html-respec.xsl index 25c24a003..b5a383bc2 100644 --- a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Kadaster-html-respec.xsl +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Kadaster-html-respec.xsl @@ -13,90 +13,8 @@ <xsl:import href="common/Imvert2modeldoc-html-respec.xsl"/> - <xsl:param name="catalog-only">true</xsl:param><!-- deze parameter is true wanneer cli/fullrespec is false --> - <xsl:template match="/book"> - <xsl:variable name="catalog" as="element(section)*"> - <xsl:apply-templates select="chapter"/><!-- calls upon the standard template for chapters such as CAT and REF --> - </xsl:variable> - <xsl:choose> - <xsl:when test="imf:boolean($catalog-only)"> - <xsl:sequence select="$catalog"/> - </xsl:when> - <xsl:otherwise> - <html> - <head> - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> - <title> - <xsl:value-of select="concat('Catalogus conceptueel model: ',@name)"/> - - - - - -
      -

      - (Abstract:) Samenvatting model..... INSERT HERE -

      -
      -
      -

      - (Status van dit document:) Deze documentatie van het model is laatst bijgewerkt op . -

      -
      -
      -

      Proloog

      -

      - Proloog model hier. -

      -
      - -
      -

      Epiloog

      -

      - Epiloog model hier. -

      -
      - - - - +
      @@ -106,13 +24,6 @@ - - - - -
      - x?> diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Kennisnet-MBG-10-UGM-html-respec.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Kennisnet-MBG-10-UGM-html-respec.xsl index 2d8e1c0a9..86c5d6496 100644 --- a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Kennisnet-MBG-10-UGM-html-respec.xsl +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Kennisnet-MBG-10-UGM-html-respec.xsl @@ -13,66 +13,8 @@ - - - - - - - <xsl:value-of select="concat('Catalogus conceptueel model: ',@name)"/> - - - - - -
      -

      - Samenvatting conceptueel model..... INSERT HERE -

      -
      -
      -

      - Deze documentatie van het conceptueel model is laatst bijgewerkt op . -

      -
      -
      -

      Proloog

      -

      - Proloog conceptueel model hier. -

      -
      - -
      -

      Epiloog

      -

      - Epiloog conceptueel model hier. -

      -
      - - +
      diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Kennisnet-MIM-11-SIM-html-respec.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Kennisnet-MIM-11-SIM-html-respec.xsl index 2d8e1c0a9..86c5d6496 100644 --- a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Kennisnet-MIM-11-SIM-html-respec.xsl +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Kennisnet-MIM-11-SIM-html-respec.xsl @@ -13,66 +13,8 @@ - - - - - - - <xsl:value-of select="concat('Catalogus conceptueel model: ',@name)"/> - - - - - -
      -

      - Samenvatting conceptueel model..... INSERT HERE -

      -
      -
      -

      - Deze documentatie van het conceptueel model is laatst bijgewerkt op . -

      -
      -
      -

      Proloog

      -

      - Proloog conceptueel model hier. -

      -
      - -
      -

      Epiloog

      -

      - Epiloog conceptueel model hier. -

      -
      - - +
      diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Logius-MIM-12-CONCEPTUAL-html-respec.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Logius-MIM-12-CONCEPTUAL-html-respec.xsl index 793be0769..86c5d6496 100644 --- a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Logius-MIM-12-CONCEPTUAL-html-respec.xsl +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Logius-MIM-12-CONCEPTUAL-html-respec.xsl @@ -13,58 +13,8 @@ - - - - - - - <xsl:value-of select="concat('Catalogus: ',@name)"/> - - - - - -
      -

      - Samenvatting..... INSERT HERE -

      -
      -
      -

      - This documentation is updated at .... INSERT HERE -

      -
      -
      -

      Prologue

      -

      - Intro here........ -

      -
      - -
      -

      Epilogue

      -

      - Last remarks here........ -

      -
      - - +
      diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Waarderingskamer-MIM-11-SIM-html-respec.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Waarderingskamer-MIM-11-SIM-html-respec.xsl index 48478e284..86c5d6496 100644 --- a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Waarderingskamer-MIM-11-SIM-html-respec.xsl +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Waarderingskamer-MIM-11-SIM-html-respec.xsl @@ -13,109 +13,8 @@ - true - - - - - - - - - - - - - - <xsl:value-of select="concat('Catalogus conceptueel model: ',@name)"/> - - - - - -
      -

      - Samenvatting conceptueel model..... INSERT HERE -

      -
      -
      -

      - Deze documentatie van het conceptueel model is laatst bijgewerkt op . -

      -
      -
      -

      Proloog

      -

      - Proloog conceptueel model hier. -

      -
      - -
      -

      Epiloog

      -

      - Epiloog conceptueel model hier. -

      -
      - - -
      -
      +
      diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Waterschapshuis-MIM-12-CONCEPTUAL-html-msword.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Waterschapshuis-MIM-12-CONCEPTUAL-html-msword.xsl index 44aeae28a..e9d9a103f 100644 --- a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Waterschapshuis-MIM-12-CONCEPTUAL-html-msword.xsl +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Waterschapshuis-MIM-12-CONCEPTUAL-html-msword.xsl @@ -14,7 +14,7 @@ - + <xsl:value-of select="$subpath"/> diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Waterschapshuis-MIM-12-CONCEPTUAL-html-respec.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Waterschapshuis-MIM-12-CONCEPTUAL-html-respec.xsl index 793be0769..86c5d6496 100644 --- a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Waterschapshuis-MIM-12-CONCEPTUAL-html-respec.xsl +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-Waterschapshuis-MIM-12-CONCEPTUAL-html-respec.xsl @@ -13,58 +13,8 @@ <xsl:import href="common/Imvert2modeldoc-html-respec.xsl"/> - <!-- this owner generates respec files with all info stored in that file. --> - <xsl:template match="/book"> - <html> - <head> - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> - <title> - <xsl:value-of select="concat('Catalogus: ',@name)"/> - - - - - -
      -

      - Samenvatting..... INSERT HERE -

      -
      -
      -

      - This documentation is updated at .... INSERT HERE -

      -
      -
      -

      Prologue

      -

      - Intro here........ -

      -
      - -
      -

      Epilogue

      -

      - Last remarks here........ -

      -
      - - +
      diff --git a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-lists.xsl b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-lists.xsl index dc63905ab..663b100fa 100644 --- a/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-lists.xsl +++ b/src/main/resources/xsl/OfficeCompiler/Imvert2modeldoc-lists.xsl @@ -44,10 +44,13 @@ - + + + + - + diff --git a/src/main/resources/xsl/OfficeCompiler/OfficeCompiler-report.xsl b/src/main/resources/xsl/OfficeCompiler/OfficeCompiler-report.xsl index 3e3bdd0a1..ca575b6de 100644 --- a/src/main/resources/xsl/OfficeCompiler/OfficeCompiler-report.xsl +++ b/src/main/resources/xsl/OfficeCompiler/OfficeCompiler-report.xsl @@ -37,7 +37,9 @@ - + + + @@ -52,7 +54,9 @@ - + + + @@ -70,33 +74,47 @@

      The preview supplied may show flaws as the intended publication environment is not available here.

      -

      The model documentation is packaged in this Imvertor model release for further processing.

      +

      The model documentation is packaged in this Imvertor model release for publication or further processing.

      +
      +

      XHTML catalog

      +

      Click here (opens new tab) for the XHTML result file.

      +

      MsWord documentation

      The HTML document may be opened in MsWord. In order to apply specific styles to the markup, the contents of the MsWord document may be copied to the clipboard, and pasted into a template document, or styles from a template document may be applied to the just created MsWord document.

      -

      Click here for the packaged documentation files.

      +

      Click here (opens new tab) for the packaged documentation files.

      -

      Respec documentation

      -

      Click here for the packaged documentation file. Use Control-Click to ensure correct rendering of the Respec file.

      +

      Partial Respec documentation

      +

      This document has been compiled without any Respec profile, and holds a basic catalog in Respec format. It may be used to include within a Respec document..

      +

      Click here (opens new tab) for the packaged partial documentation file.

      -
      -

      External documentation

      -

      Click here for the packaged externally compiled documentation. Use Control-Click to ensure correct rendering of the Respec file.

      -

      Please consult your Imvertor provider if the link does not resolve to a valid HTML document.

      -
      - + +
      +

      Stand-alone Respec documentation

      + + +

      This document has been compiled using Documentor. It may be used for publication.

      +
      + +

      This document has been compiled using a simple W3C Respec profile. It should not be used for publication.

      +
      +
      +

      Click here (opens new tab) for the packaged full documentation file.

      +
      +
      +
      diff --git a/src/main/resources/xsl/OfficeCompiler/common/Imvert2documentor-respec-pack-complete-respec.xsl b/src/main/resources/xsl/OfficeCompiler/common/Imvert2documentor-respec-pack-complete-respec.xsl new file mode 100644 index 000000000..86b78bc47 --- /dev/null +++ b/src/main/resources/xsl/OfficeCompiler/common/Imvert2documentor-respec-pack-complete-respec.xsl @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      diff --git a/src/main/resources/xsl/Reporter/Reporter-report.xsl b/src/main/resources/xsl/Reporter/Reporter-report.xsl index 1dc0a8c25..5a04ce459 100644 --- a/src/main/resources/xsl/Reporter/Reporter-report.xsl +++ b/src/main/resources/xsl/Reporter/Reporter-report.xsl @@ -350,6 +350,8 @@
      + +
      @@ -363,6 +365,8 @@
      + +
      diff --git a/src/main/resources/xsl/Tools/Propcollector/Propcollector.xml b/src/main/resources/xsl/Tools/Propcollector/Propcollector.xml new file mode 100644 index 000000000..816574cd9 --- /dev/null +++ b/src/main/resources/xsl/Tools/Propcollector/Propcollector.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/resources/xsl/Tools/Propcollector/Propcollector.xsl b/src/main/resources/xsl/Tools/Propcollector/Propcollector.xsl new file mode 100644 index 000000000..990346506 --- /dev/null +++ b/src/main/resources/xsl/Tools/Propcollector/Propcollector.xsl @@ -0,0 +1,53 @@ + + + file:/D:/Projects/gitprojects/Imvertor-Maven/src/main/resources/cfg + + + + + + + + + + + {$file} + + + + + + + + + + + + + +
      +

      Pxxx: {name}

      + +

      {tip}

      +

      Waarde: {arg}, type: {(type,'string')[1]}, verplicht: {required}, default: {(default,'(geen)')[1]}

      + +

      Context: {context}

      +
      + +

      Module: {$toks[count($toks) - 1]} ({root(.)/config/id/name})

      + + + +

      {desc}

      +
      +
      + + + + + +
      \ No newline at end of file diff --git a/src/main/resources/xsl/Validator/Imvert2validation.xsl b/src/main/resources/xsl/Validator/Imvert2validation.xsl index af56ed184..3a01a094c 100644 --- a/src/main/resources/xsl/Validator/Imvert2validation.xsl +++ b/src/main/resources/xsl/Validator/Imvert2validation.xsl @@ -173,6 +173,8 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/xsl/common/extension/imvert-common-hash.xsl b/src/main/resources/xsl/common/extension/imvert-common-hash.xsl new file mode 100644 index 000000000..12e53d182 --- /dev/null +++ b/src/main/resources/xsl/common/extension/imvert-common-hash.xsl @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + \ No newline at end of file