diff --git a/build.gradle b/build.gradle index 129da29e..20f94385 100644 --- a/build.gradle +++ b/build.gradle @@ -18,8 +18,8 @@ buildscript { classpath group: 'org.docbook', name: 'docbook-schemas', version: '5.1-1' classpath group: 'com.xmlcalabash', name: 'xmlcalabash1-print', version: '1.1.5' classpath group: 'com.xmlcalabash', name: 'xmlcalabash1-gradle', version: '1.4.0' - classpath group: 'com.xmlcalabash', name: 'xmlcalabash', version: '1.3.2-99' - classpath group: 'org.xmlresolver', name: 'xmlresolver', version: '3.0.2' + classpath group: 'com.xmlcalabash', name: 'xmlcalabash', version: '1.5.7-120' + classpath group: 'org.xmlresolver', name: 'xmlresolver', version: '5.3.0' } } diff --git a/src/main/resources/js/scroll.js b/src/main/resources/js/scroll.js new file mode 100644 index 00000000..1c2ece82 --- /dev/null +++ b/src/main/resources/js/scroll.js @@ -0,0 +1,411 @@ +const DELETED = "rgb(255, 85, 85, 0.3)"; +const ADDED = "rgb(144, 238, 144, 0.3)"; + +class DXmlView { + constructor() { + this.body = document.querySelector("body"); + + this.old_classes = ["deltaxml-old", "deltaxml-old-img", "deltaxml-old-format"]; + this.new_classes = ["deltaxml-new", "deltaxml-new-img", "deltaxml-new-format"]; + this.del_classes = ["delete_version"]; + this.add_classes = ["add_version"]; + this.mod_classes = ["modify_version"]; + + this.all_classes = []; + this.old_classes.forEach(name => { this.all_classes.push(name); }); + this.new_classes.forEach(name => { this.all_classes.push(name); }); + this.del_classes.forEach(name => { this.all_classes.push(name); }); + this.add_classes.forEach(name => { this.all_classes.push(name); }); + this.mod_classes.forEach(name => { this.all_classes.push(name); }); + + // Turn the classes into selector patterns + let patterns = []; + this.all_classes.forEach(name => { patterns.push("."+name); }); + + this.all_selector = patterns.join(","); + + // Select any element in the ToC; we want to exclude these + // because they're in a separate scroll and that messes with + // with the next/previous functionality + let tocSelector = ""; + patterns.forEach(pattern => { + if (tocSelector !== "") { + tocSelector += ","; + } + tocSelector += "#toc " + pattern; + }); + + this.toc_diff = []; + document.querySelectorAll(tocSelector).forEach(item => { + this.toc_diff.push(item); + }); + + this.all_diff = []; + this.xml_diff = []; + document.querySelectorAll(this.all_selector).forEach(item => { + this.all_diff.push(item); + if (!this.toc_diff.includes(item)) { + this.xml_diff.push(item); + } + }); + + this.visible_diff = []; + this.visible_offset = []; + this.recalculate = true; + this.fading = false; + this.stylemap = new Map(); + + this.fadingMessage(`  (${this.xml_diff.length.toLocaleString()} differences)`); + } + + fadingMessage(message) { + let span = document.querySelector("#__autodiff__"); + if (span) { + span.innerHTML = message; + span.className = "autoshow"; + + if (!this.fading) { + this.fading = true; + let outer = this; + setTimeout(function(){ + span.className = "autohide"; + setTimeout(function(){ + span.innerHTML = ""; + span.className = ""; + outer.fading = false; + }, 5000); + }, 100); + } + } + } + + absoluteTop(item) { + let top = item.offsetTop; + while (item && item.offsetParent !== this.body) { + item = item.offsetParent; + if (item === null) { + return -1; + } + top += item.offsetTop; + } + return top; + } + + find_visible_diffs() { + this.visible_diff = []; + this.visible_offset = []; + this.xml_diff.forEach(item => { + let ofs = this.absoluteTop(item); + if (ofs >= 0) { + this.visible_diff.push(item); + this.visible_offset.push(ofs); + } + }); + this.recalculate = false; + window.DIFF = this.visible_diff; + } + + scroll_forward() { + if (this.recalculate) { + this.find_visible_diffs(); + } + + let topY = window.scrollY; + let bottomY = window.scrollY + window.innerHeight - 1; + let halfY = (bottomY - topY) / 2; + + let curOffset = 0; + let cur_diff = 0; + while (cur_diff < this.visible_offset.length + && this.visible_offset[cur_diff] < topY) { + cur_diff++; + curOffset = this.visible_offset[cur_diff]; + } + + while (curOffset < bottomY && cur_diff < this.visible_diff.length) { + cur_diff++; + curOffset = this.visible_offset[cur_diff]; + } + + if (cur_diff < this.visible_diff.length) { + window.scrollTo(0, curOffset - halfY); + this.fadingMessage(`Difference ${cur_diff.toLocaleString()} of ${this.xml_diff.length.toLocaleString()}.`); + } else { + this.fadingMessage("There are no more following differences."); + } + } + + scroll_backward() { + if (this.recalculate) { + this.find_visible_diffs(); + } + + let topY = window.scrollY; + let bottomY = window.scrollY + window.innerHeight - 1; + let halfY = (bottomY - topY) / 2; + + let curOffset = 0; + let cur_diff = 0; + while (cur_diff < this.visible_offset.length + && this.visible_offset[cur_diff] < topY) { + cur_diff++; + curOffset = this.visible_offset[cur_diff]; + } + + if (cur_diff > 0) { + cur_diff--; + curOffset = this.visible_offset[cur_diff]; + if (cur_diff < this.visible_diff.length) { + window.scrollTo(0, curOffset - halfY); + this.fadingMessage(`Difference ${cur_diff.toLocaleString()} of ${this.xml_diff.length.toLocaleString()}.`); + } + } else { + this.fadingMessage("The are no more preceding differences."); + } + } + + displayType(span) { + if (span.localName === "tr") { + return "table-row"; + } + + if (span.localName === "li") { + return "list-item"; + } + + return "inline"; + } + + view_old() { + this.restore_view(); + this.all_diff.forEach(span => { + let displayType = this.displayType(span); + if (this.old_classes.includes(span.className) || this.del_classes.includes(span.className)) { + span.style.display = displayType; + span.style.background="#FFF"; + //need to take border off images + span.querySelectorAll("img").forEach(img => { + img.style.border = "none"; + }); + } else { + span.style.display = "none"; + } + }); + } + + view_new() { + this.restore_view(); + this.all_diff.forEach(span => { + let displayType = this.displayType(span); + if (this.new_classes.includes(span.className) || this.add_classes.includes(span.className)) { + span.style.display = displayType; + span.style.background = "#FFF"; + //need to take border off images + span.querySelectorAll("img").forEach(img => { + img.style.border = "none"; + }); + } else { + span.style.display = "none"; + } + }); + } + + view_both() { + this.restore_view(); + this.all_diff.forEach(span => { + let displayType= this.displayType(span); + if (this.new_classes.includes(span.className)) { + span.style.display = displayType; + span.style.background = ADDED + //need to add border to images + span.querySelectorAll("img").forEach(img => { + img.style.border = "2px solid green"; + }); + } else if (this.old_classes.includes(span.className)) { + span.style.display = displayType; + span.style.background = DELETED; + //need to add border to images + span.querySelectorAll("img").forEach(img => { + img.style.border = "2px solid red"; + }); + } else if (this.add_classes.includes(span.className) + || this.del_classes.includes(span.className)) { + span.style.display = "none"; + } else { + span.style.display= displayType; + } + }); + } + + view_only() { + this.restore_view(); + this.recursediffs(document.querySelector("body")); + let buttons = document.querySelector("#_autodiff_buttons"); + if (buttons) { + buttons.style.display = "block"; + } + this.recalculate = true; + } + + restore_view() { + if (this.stylemap.size === 0) { + return; + } + + const nodeIter = this.stylemap.entries(); + let item = nodeIter.next(); + while (!item.done) { + const node = item.value[0]; + for (const [key, value] of Object.entries(item.value[1])) { + if (node.style) { + node.style[key] = value; + } else { + node.style.display = value; + } + } + item = nodeIter.next(); + } + + this.stylemap.clear(); + this.recalculate = true; + } + + recursediffs(root) { + for (const child of root.children) { + this.stylemap.set(child, {'display': child.style.display}); + + // Don't bother computing the intersection if child.classList is empty + let intersect = []; + if (child.classList.length > 0) { + intersect = this.all_classes.filter(name => child.classList.contains(name)); + } + + if (intersect.length > 0) { + console.log("I:", child); + this.find_header(child); + } else { + if (child.querySelector(this.all_selector)) { + this.recursediffs(child); + } else { + child.style.display = "none"; + } + } + } + } + + find_header(node) { + let header = node.nodeName === "SECTION" + while (!header) { + node = node.parentNode + if (node.nodeName === "BODY") { + // bail! + return + } + header = node.nodeName === "SECTION" + } + let title = node.querySelector(".section-titlepage") + title.style.display = "block" + + node.style["border-top"] = "6px dotted " + DELETED; + node.style["padding-top"] = "20px"; + node.style["margin-top"] = "20px"; + } + + mark_change(node, className, color, changebarColor) { + node.classList.add(className); + node.style["background-color"] = color; + if (className == "deltaxml-old") { + node.style["text-decoration-line"] = "line-through"; + node.style["text-decoration-color"] = "#555555"; + } + + for (const child of node.children) { + child.classList.remove(className); + child.style["background-color"] = "transparent" + if (child.nodeName == "DIV" || child.nodeName == "P" || child.nodeName == "LI" + || child.nodeName == "DT" || child.nodeName == "DD") { + child.style["border-right"] = "none"; + if (className == "deltaxml-old") { + node.style["text-decoration"] = "none"; + } + } + } + + if (node.nodeName == "DIV" || node.nodeName == "P" || node.nodeName == "LI" + || node.nodeName == "DT" || node.nodeName == "DD") { + node.style["border-right"] = "6px solid " + changebarColor; + } + } + + tidy_change_markup(node, depth) { + //console.log(`WALK: ${node.nodeName} ${depth}`); + + let status = node.classList.contains("deltaxml-new") ? "new" + : (node.classList.contains("deltaxml-old") ? "old" : "undecided") + + if (status == "undecided") { + for (const child of node.children) { + this.tidy_change_markup(child, depth+1) + } + + let markOld = true + let markNew = true + for (const child of node.children) { + markOld = markOld && (child.childNodes.length == 0 || child.classList.contains("deltaxml-old")) + markNew = markNew && (child.childNodes.length == 0 || child.classList.contains("deltaxml-new")) + //console.log(` ?? ${node.nodeName}: ${markOld}/${markNew}`) + } + + if (markOld && markNew) { + status = "undecided"; + } else if (markOld) { + status = "old"; + } else if (markNew) { + status = "new"; + } else { + status = "mixed"; + } + } + + if (status == "new") { + this.mark_change(node, "deltaxml-new", ADDED, "green") + } else if (status == "old") { + this.mark_change(node, "deltaxml-old", DELETED, "red") + } + } +} + +// I'm not sure this is the cleanest approach... + +let dxmlview = new DXmlView(); +window.scroll_to = function(direction) { + if (direction == 'next') { + dxmlview.scroll_forward(); + } else if (direction === 'prev') { + dxmlview.scroll_backward(); + } else { + console.log("Unexpected scroll direction: ", direction); + } +}; + +window.view = function(doc) { + if (doc === "new") { + dxmlview.view_new(); + } else if (doc === "old") { + dxmlview.view_old(); + } else if (doc === "both") { + dxmlview.view_both(); + } else if (doc === "only") { + dxmlview.view_both(); + dxmlview.view_only(); + } else { + console.log("Unexpected view doc: ", doc); + } +}; + +window.addEventListener('resize', (event) => { + dxmlview.find_visible_diffs(); +}); + +dxmlview.view_both(); +dxmlview.tidy_change_markup(document.querySelector("body"), 0) diff --git a/step-file/src/main/xml/specification.xml b/step-file/src/main/xml/specification.xml index 66634b6b..1cad5374 100644 --- a/step-file/src/main/xml/specification.xml +++ b/step-file/src/main/xml/specification.xml @@ -6,12 +6,13 @@ xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id='step-file' - class="ed" role="step" + class="wd" role="step" version="5.0-extension w3c-xproc"> XProc 3.1: file steps 201820192020 +20212022202320242025 the Contributors to the XProc 3.1 Standard Step Library specifications @@ -62,8 +63,11 @@ for +This draft is a “last call” draft. This version is stable and will not be updated. + diff --git a/step-ixml/src/main/xml/specification.xml b/step-ixml/src/main/xml/specification.xml index bed290a1..70ada3ec 100644 --- a/step-ixml/src/main/xml/specification.xml +++ b/step-ixml/src/main/xml/specification.xml @@ -6,12 +6,13 @@ xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id='step-ixml' - class="ed" role="step" + class="wd" role="step" version="5.0-extension w3c-xproc"> XProc 3.1: Invisible XML 2021 +2022202320242025 the Contributors to the XProc 3.1 Standard Step Library specifications @@ -53,8 +54,11 @@ step for +This draft is a “last call” draft. This version is stable and will not be updated. + diff --git a/step-mail/src/main/xml/specification.xml b/step-mail/src/main/xml/specification.xml index acabf011..b9083cc5 100644 --- a/step-mail/src/main/xml/specification.xml +++ b/step-mail/src/main/xml/specification.xml @@ -5,12 +5,13 @@ xmlns:p="http://www.w3.org/ns/xproc" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" - xml:id="step-mail" class="ed" + xml:id="step-mail" class="wd" role="step" version="5.0-extension w3c-xproc"> XProc 3.1: mail steps 201820192020 +20212022202320242025 the Contributors to the XProc 3.1 Standard Step Library specifications @@ -60,8 +61,11 @@ specifications +This draft is a “last call” draft. This version is stable and will not be updated. + diff --git a/step-os/src/main/xml/specification.xml b/step-os/src/main/xml/specification.xml index 95c2915e..39b6759c 100644 --- a/step-os/src/main/xml/specification.xml +++ b/step-os/src/main/xml/specification.xml @@ -6,12 +6,13 @@ xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id='step-os' - class="ed" role="step" + class="wd" role="step" version="5.0-extension w3c-xproc"> XProc 3.1: operating system steps 201820192020 +20212022202320242025 the Contributors to the XProc 3.1 Standard Step Library specifications @@ -63,8 +64,11 @@ for +This draft is a “last call” draft. This version is stable and will not be updated. + diff --git a/step-paged-media/src/main/xml/specification.xml b/step-paged-media/src/main/xml/specification.xml index 3a80aa7b..1ba0eab8 100644 --- a/step-paged-media/src/main/xml/specification.xml +++ b/step-paged-media/src/main/xml/specification.xml @@ -6,12 +6,13 @@ xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id='step-paged-media' - class="ed" role="step" + class="wd" role="step" version="5.0-extension w3c-xproc"> XProc 3.1: paged media steps 201820192020 +20212022202320242025 the Contributors to the XProc 3.1 Standard Step Library specifications @@ -67,8 +68,11 @@ steps for An XML Pipeline Language published by the W3C. +This draft is a “last call” draft. This version is stable and will not be updated. + diff --git a/step-run/src/main/xml/specification.xml b/step-run/src/main/xml/specification.xml index c17b86ac..665e2cca 100644 --- a/step-run/src/main/xml/specification.xml +++ b/step-run/src/main/xml/specification.xml @@ -6,12 +6,12 @@ xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id='step-run' - class="ed" role="step" + class="wd" role="step" version="5.0-extension w3c-xproc"> XProc 3.1: dynamic pipeline execution -2018201920202024 +20182019202020242025 the Contributors to the XProc 3.x Standard Step Library specifications @@ -62,8 +62,11 @@ step for +This draft is a “last call” draft. This version is stable and will not be updated. + diff --git a/step-text/src/main/xml/specification.xml b/step-text/src/main/xml/specification.xml index 4d49af24..9dd99643 100644 --- a/step-text/src/main/xml/specification.xml +++ b/step-text/src/main/xml/specification.xml @@ -2,12 +2,13 @@ XProc 3.1: text steps 201820192020 +20212022202320242025 the Contributors to the XProc 3.1 Standard Step Library specifications @@ -56,8 +57,11 @@ specifications +This draft is a “last call” draft. This version is stable and will not be updated. + diff --git a/step-validation/src/main/xml/specification.xml b/step-validation/src/main/xml/specification.xml index fc17291d..7d2e2c1c 100644 --- a/step-validation/src/main/xml/specification.xml +++ b/step-validation/src/main/xml/specification.xml @@ -7,12 +7,13 @@ xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id='step-validation' - class="ed" role="step" + class="wd" role="step" version="5.0-extension w3c-xproc"> XProc 3.1: validation steps 201820192020 +20212022202320242025 the Contributors to the XProc 3.1 Standard Step Library specifications @@ -73,8 +74,11 @@ step for An XML Pipeline Language published by the W3C. +This draft is a “last call” draft. This version is stable and will not be updated. + diff --git a/steps/src/main/xml/specification.xml b/steps/src/main/xml/specification.xml index b67061a7..db58b99d 100644 --- a/steps/src/main/xml/specification.xml +++ b/steps/src/main/xml/specification.xml @@ -6,7 +6,7 @@ xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id='steps' - class="ed" + class="wd" version="5.0-extension w3c-xproc"> XProc 3.1: Standard Step Library @@ -15,7 +15,7 @@ https://spec.xproc.org/3.0/steps/ --> 20182019202020212022 -20232024 +202320242025 the Contributors to the XProc 3.1 Standard Step Library specifications @@ -69,8 +69,11 @@ specifications +This draft is a “last call” draft. This version is stable and will not be updated. + This document is derived from @@ -291,6 +294,21 @@ PSVI annotations. +Resolved issue 659 +by updating the p:cast-content-type step. Added the p:encode step. +This is a small backwards incompatibility because it means that you cannot use +p:cast-content type to change the content type of a c:data element from +application/xml to, for example, application/foo+xml. That seems +like an unlikely scenario because XProc controls the semantics of c:data +documents. + + +Resolved issue 642 +by removing the distinction between “has no value” and “the empty sequence” in the +p:xslt step. This means it is no longer possible to specify a single document +on the source port and have the global context item be the empty sequence. + + Resolved issue 549 by making the result output port on p:compare primary. Although this change is technically backwards incompatible, all known implementations of @@ -312,6 +330,48 @@ to recognize the incorrect value, perhaps with a warning. +Resolved issue 668 +by clarifying explicitly how the Unicode byte order mark is processed. + + + +Resolved issue 656 +by adding an option to p:pack, p:wrap, and +p:wrap-sequence. + + + +Resolved issue 647 +by allowing the value of the option on p:sleep to be +either a number of seconds or an xs:dayTimeDuration. + + + +Resolved issue 644 +by allowing p:filter to return non-node results. + + + +Resolved issue 635 +by clarifying how a text document can be produced from the p:filter step. + + + +Resolved issue 623 +by clarifying the semantics of p:error. + + + +Added a description of c:parameter-set documents. + + +Added the p:message step. + + + +Several error codes were added. + + Resolved issue 587 by adding a option to the p:uuid step. @@ -336,6 +396,28 @@ allowing text documents on the result port. +Added a normative reference to RFC 8259 for the JSON format. + + +Clarified the relationship between the p:text-sort step and the +xsl:sort element. + + +Made editorial improvements to the description of p:http-request and +p:load. + + + +Resolved issue 678 +by describing the comment attribue in the archive manifest. + + + +Resolved issue 639 +by removing the superflous mention of PSVI annotations in the p:split-sequence step. + + + Resolved issue 580 by clarifying what standards apply to the option on p:text-sort.