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.