Skip to content

Commit e5ed69e

Browse files
committed
result messages can have a reference which is a URL
1 parent dffe26e commit e5ed69e

File tree

3 files changed

+64
-16
lines changed

3 files changed

+64
-16
lines changed

bin/rdap-validator

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const MSG_FAIL = "\x1b[1;31m✘\x1b[0m";
5252
const MSG_PASS = "\x1b[1;32m✓\x1b[0m";
5353
const MSG_INFO = "\x1b[1;33mi\x1b[0m";
5454

55-
const cliResultCallback = function(result, message, path) {
55+
const cliResultCallback = function(result, message, path, ref) {
5656
const onlyErrors = opt.named.hasOwnProperty("only-errors");
5757
const depth = rdapValidator.path.length;
5858
const indent = INDENT_STRING.repeat(onlyErrors ? 0 : Math.max(0, depth-1)) + "- ";
@@ -73,11 +73,12 @@ const cliResultCallback = function(result, message, path) {
7373
lastDepth = depth;
7474
};
7575

76-
const jsonResultCallback = function(result, message, path) {
76+
const jsonResultCallback = function(result, message, path, ref) {
7777
jsonResultData.results.push({
7878
testPassed: result,
7979
message: message,
8080
path: path,
81+
reference: ref,
8182
});
8283
};
8384

lib/rdap-validator.js

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,24 @@ const self = rdapValidator;
44

55
export default rdapValidator;
66

7+
self.referenceBase = "https://validator.rdap.org/specs/";
8+
9+
self.referenceURLs = {
10+
"rfc7480": "vanilla/rfc7480.html",
11+
"rfc7481": "vanilla/rfc7481.html",
12+
"rfc9082": "vanilla/rfc9082.html",
13+
"rfc9083": "vanilla/rfc9083.html",
14+
"rfc9224": "vanilla/rfc9224.html",
15+
"rfc9537": "vanilla/rfc9537.html",
16+
"feb24-rp": "gtld/2024-02/rdap-response-profile-21feb24-en.pdf",
17+
"feb24-tig": "gtld/2024-02/rdap-technical-implementation-guide-21feb24-en.pdf",
18+
"nro": "rir/2021-01/nro-rdap-profile.txt",
19+
};
20+
21+
self.ref = function(f, spec=null) {
22+
return self.referenceBase + self.referenceURLs[spec ?? self.currentSpec] + "#" + f;
23+
}
24+
725
/**
826
* Initiate a test run.
927
* @param {null|string} url
@@ -12,6 +30,8 @@ export default rdapValidator;
1230
*/
1331
self.testURL = function(url, type, serverType) {
1432

33+
self.currentSpec = "rfc7480";
34+
1535
self.errors = 0;
1636

1737
if (!self.responseTypes.hasOwnProperty(type)) {
@@ -83,22 +103,26 @@ self.testResponse = function(xhr, url, type, serverType) {
83103

84104
if (!self.add(
85105
"error" == type ? xhr.status >= 400 : xhr.status < 400,
86-
"HTTP status " + xhr.status + " MUST be " + ("error" == type ? "> 400 or higher" : "less than 400")
106+
"HTTP status " + xhr.status + " MUST be " + ("error" == type ? "> 400 or higher" : "less than 400"),
107+
"error" == type ? "section-5.3" : "section-5.1",
87108
)) return;
88109

89110
if (!self.add(
90111
self.lastTestedResponseHeaders["content-type"].toLowerCase().startsWith("application/rdap+json"),
91-
"Media type '" + self.lastTestedResponseHeaders["content-type"] + "' SHOULD be is application/rdap+json."
112+
"Media type '" + self.lastTestedResponseHeaders["content-type"] + "' SHOULD be application/rdap+json.",
113+
"section-4.2",
92114
)) return;
93115

94116
var record;
95117

118+
self.currentSpec = "rfc9083";
119+
96120
try {
97121
record = JSON.parse(xhr.response ?? xhr.responseText);
98-
self.add(true, "Response body MUST be valid JSON.");
122+
self.add(true, "Response body MUST be valid JSON.", "name-introduction");
99123

100124
} catch (e) {
101-
self.add(false, "Response body MUST be valid JSON (parse error: " + e + ").");
125+
self.add(false, "Response body MUST be valid JSON (parse error: " + e + ").", "name-introduction");
102126

103127
return;
104128
}
@@ -107,7 +131,8 @@ self.testResponse = function(xhr, url, type, serverType) {
107131

108132
if (!self.add(
109133
self.isObject(record),
110-
"Response body MUST be a JSON object."
134+
"Response body MUST be a JSON object.",
135+
"section-5",
111136
)) return;
112137

113138
self.validateRDAPConformance(record);
@@ -219,16 +244,19 @@ self.validateRDAPConformance = function(record) {
219244

220245
if (self.add(
221246
record.hasOwnProperty("rdapConformance"),
222-
"Record MUST have the 'rdapConformance' property."
247+
"Record MUST have the 'rdapConformance' property.",
248+
"section-4.1",
223249
)) {
224250
self.add(
225251
self.isArray(record.rdapConformance),
226-
"The 'rdapConformance' property MUST be an array."
252+
"The 'rdapConformance' property MUST be an array.",
253+
"section-4.1",
227254
);
228255

229256
self.add(
230257
record.rdapConformance.indexOf("rdap_level_0") >= 0,
231-
"The 'rdapConformance' property MUST contain 'rdap_level_0'."
258+
"The 'rdapConformance' property MUST contain 'rdap_level_0'.",
259+
"section-4.1",
232260
);
233261
}
234262

@@ -2443,8 +2471,9 @@ self.countryCodes = [
24432471
* @param {string} message
24442472
* @param {mixed} context
24452473
* @param {string} path
2474+
* @param {string} ref
24462475
*/
2447-
self.resultCallback = (result, message, path) => null;
2476+
self.resultCallback = (result, message, path, ref) => null;
24482477

24492478
/**
24502479
* Specify a callback to invoke when a result has been generated. This callback
@@ -2479,10 +2508,11 @@ self.setTestCompleteCallback = function(callback) {
24792508
* Log a result by invoking the resultCallback with the provided arguments.
24802509
* @param {bool} result
24812510
* @param {string} message
2511+
* @param {string} ref
24822512
*/
2483-
self.add = function(result, message) {
2513+
self.add = function(result, message, ref) {
24842514
if (false === result) self.errors++;
2485-
self.resultCallback(result, message, self.getPath());
2515+
self.resultCallback(result, message, self.getPath(), ref ? self.ref(ref) : undefined);
24862516
return result;
24872517
};
24882518

lib/spa.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ function scrollParentToChild(parent, child) {
105105

106106
}
107107

108-
rdapValidator.setResultCallback(function(result, message, path) {
108+
rdapValidator.setResultCallback(function(result, message, path, ref) {
109109

110110
if (false !== result && document.getElementById("errors-only").checked) return;
111111

@@ -115,9 +115,11 @@ rdapValidator.setResultCallback(function(result, message, path) {
115115

116116
message = (null === result ? "ℹ️" : (true === result ? "✅" : "❌")) + message;
117117

118-
li.appendChild(document.createTextNode(message));
118+
const msgspan = document.createElement("span");
119+
msgspan.appendChild(document.createTextNode(message));
120+
msgspan.title = path;
119121

120-
li.title = path;
122+
li.appendChild(msgspan);
121123

122124
if ("$" !== path) {
123125
li.addEventListener("click", function(event) {
@@ -146,6 +148,21 @@ rdapValidator.setResultCallback(function(result, message, path) {
146148

147149
});
148150
}
151+
152+
if (ref) {
153+
li.appendChild(document.createTextNode(" "));
154+
155+
const a = li.appendChild(document.createElement("a"));
156+
157+
a.appendChild(document.createTextNode("📖"));
158+
159+
a.setAttribute("href", ref);
160+
a.setAttribute("target", "_blank");
161+
a.setAttribute("title", "Open link to specification in a new window");
162+
163+
a.style.setProperty("vertical-align", "super");
164+
a.style.setProperty("font-size", "small");
165+
}
149166
});
150167

151168
function JSONPathParent(path) {

0 commit comments

Comments
 (0)