-
Notifications
You must be signed in to change notification settings - Fork 56
Expand file tree
/
Copy pathprofile.js
More file actions
159 lines (146 loc) · 5.8 KB
/
profile.js
File metadata and controls
159 lines (146 loc) · 5.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/**
* Pseudo-rule for metadata extraction: profile.
*/
/** @import { Specberus } from "../../validator.js" */
// Internal packages:
import { allProfiles, importJSON } from '../../util.js';
import { sortedProfiles } from '../../views.js';
import { check as getTitle } from './title.js';
const rules = importJSON('../../rules.json', import.meta.url);
// 'self.name' would be 'metadata.profile'
export const name = 'metadata.profile';
/**
* @param {Specberus} sr
* @param done
*/
export async function check(sr, done) {
let matchedLength = 0;
let id;
let $profileEl;
const reviewStatus = new Map();
const $stateEl = sr.getDocumentStateElement();
if (!$stateEl) {
sr.throw(
'Cannot find the <code><p id="w3c-state"></code> element for profile and date.<br><br>Please make sure the <code><p id="w3c-state"><a href="https://www.w3.org/standards/types#@@Profile">W3C @@Profile</a>, DD Month Year</p></code> element can be selected by <code>document.getElementById(\'w3c-state\')</code>; <br>If you are using bikeshed, please update to the latest version.'
);
}
const candidate = $stateEl && sr.norm($stateEl.text()).toLowerCase();
if (candidate) {
for (const t in rules)
if (t !== '*')
for (const p in rules[t].profiles) {
const name = rules[t].profiles[p].name.toLowerCase();
if (
candidate.indexOf(name) !== -1 &&
matchedLength < name.length
) {
id = p;
$profileEl = $stateEl;
matchedLength = name.length;
}
}
}
reviewStatus.set('CR', 'implementationFeedbackDue');
reviewStatus.set('PR', 'prReviewsDue');
reviewStatus.set('CRY', 'cryFeedbackDue');
/**
* @param id
* @param {Specberus} sr
*/
function assembleMeta(id, sr) {
let meta = { profile: id };
if (reviewStatus.has(id)) {
const dueDate = sr.getFeedbackDueDate();
const dates = dueDate && dueDate.valid;
let res = dates[0];
if (dates.length === 0 || !res) return done({ profile: id });
if (dates.length > 1) res = new Date(Math.min.apply(null, dates));
const d = [
res.getFullYear(),
res.getMonth() + 1,
res.getDate(),
].join('-');
meta[reviewStatus.get(id)] = d;
}
// implementation report
if (['CR', 'CRD', 'PR', 'REC'].indexOf(id) > -1) {
const dts = sr.extractHeaders();
if (dts.Implementation?.$dd?.find('a').length) {
meta.implementationReport = dts.Implementation.$dd
.find('a')
.first()
.attr('href');
}
}
if (id === 'REC') {
meta = sr.getRecMetadata(meta);
}
// Get 'track/rectrack' of the document based on id
const profileRex = new RegExp(
`SUBM|(TR/(Registry|Recommendation|Note))/(${id}).js`
);
const thisProfile = allProfiles.filter(eachProfile =>
// eg for eachProfile: 'TR/Note/NOTE-Echidna.js'
profileRex.test(eachProfile)
);
const profileMatch =
thisProfile.length && thisProfile[0].match(profileRex);
const track = profileMatch && profileMatch[profileMatch.length - 2];
meta.rectrack = track;
return done(meta);
}
const checkRecType = function () {
if (
$profileEl &&
sr.norm($profileEl.text()).indexOf('Candidate Recommendation') > 0
) {
return sr.norm($profileEl.text()).indexOf('Draft') > 0
? 'CRD'
: 'CR';
}
return 'REC';
};
if (id) {
// W3C Candidate Recommendation (CR before 2020/CR snapshot/CR draft), W3C Recommendation will have "REC"
if (id === 'REC' || id === 'CR') {
// distinguish REC CR CRD
id = checkRecType();
}
if (id === 'CRY') {
// distinguish CRY CRYD
id =
sr.norm($profileEl.text()).indexOf('Draft') > 0
? 'CRYD'
: 'CRY';
}
assembleMeta(id, sr);
} else {
let docTitle;
await getTitle(sr, result => {
docTitle = result && result.title;
});
if (candidate && candidate.indexOf("editor's draft") > -1) {
sr.throw(
`[EXCEPTION] The document "${docTitle}" seems to be an Editor's Draft, which is not supported.`
);
} else if (
sr.$('link[href^="https://www.w3.org/StyleSheets/TR/"]').length
) {
let profileList = '';
sortedProfiles.forEach(category => {
profileList += `${category.name}<ul>`;
category.profiles.forEach(profile => {
profileList += `<li>W3C state element for <a href="./doc/rules/?profile=${profile.abbr}#dateState">${profile.name}</a></li>`;
});
profileList += '</ul>';
});
sr.throw(
`Pubrules is having a hard time identifying the profile of the document "${docTitle}" from its w3c-state element; Please make sure the <p id="w3c-state"> is in a valid format: <pre><code><p id="w3c-state"><a href="https://www.w3.org/standards/types#@@Profile">W3C @@type of the document@@</a> DD Month YYYY</p></code></pre>${profileList}`
);
} else {
sr.throw(
`[EXCEPTION] The document "${docTitle}" could not be parsed, it's neither a TR document nor a Member Submission.`
);
}
}
}