-
Notifications
You must be signed in to change notification settings - Fork 694
/
Copy pathissuegen.pl
executable file
·338 lines (292 loc) · 10.9 KB
/
issuegen.pl
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
#!/usr/bin/perl
use strict;
# Color coding
# Note statuses will get lowercased before lookup
my %statusStyle = (
'accepted' => 'a',
'retracted' => 'a',
'rejected' => 'r',
'objection' => 'fo',
'deferred' => 'd',
'invalid' => 'oi',
'outofscope' => 'oi',
);
# Header template is at the end of the file
################################################################################
my $inFile = $ARGV[0];
if (!$inFile) {
print "\nPass in issues list filename for processing!";
print "\nOr use argument 'help' for help.\n\n";
print "~~~~~~~~~~~~~~~~~~~~~ Template for issues-list.txt ~~~~~~~~~~~~~~~~~~~~~\n";
print <<XXX;
Draft: http://www.w3.org/TR/2013/WD-css-text-decor-3-20130103/
Title: CSS Text Decoration Level 3
... any HTML intro content you want here, except 4 consecutive dashes ...
----
Issue 1.
Summary: [summary]
From: [name]
Comment: [url]
Response: [url]
Changes: [changeset(s) or new section or left blank for “It's complicated.” ]
Closed: Accepted/OutOfScope/Invalid/Rejected/Retracted/Deferred ... or replace this line with "Open"
Verified: [url]
Resolved: Editorial/Bugfix (for obvious fixes)/Editor discretion/[url to minutes]
----
XXX
exit;
}
if ($inFile eq 'help') {
print <<XXX;
Welcome to fantasai's Issues List Generator!
This is a script that converts a plaintext (.txt or .bsi) issues list
into a color-coded HTML file of the same name (but .html file extension).
The input is itself a presentable, easily-editable file designed
mostly for the editor’s convenience.
The original purpose of this format is to create a Disposition of
Comments for the W3C's LCWD->CR transition process. However, it is
also useful for tracking issues in general and can be used as such.
There is no requirement to use this format; fantasai merely found it
the most convenient way to track issues and create a DoC.
Beyond the header, the script itself only processes the dividers,
the issue number, and the status (Closed/Open). Additional fields
may be added or removed as desired; they are merely passed through.
fantasai suggests the following fields, as seen in the template:
Summary: A one-line summary of the issue, so that a reviewer can
quickly grasp what the issue was about.
From: The name of the commenter.
Comment: URL to the message that most clearly presents the issue.
Usually the initial message in a thread, but not always.
This is the hook into the discussion, where further details
can be read.
Response: URL to the editor’s response that is intended to close
the issue: usually either reporting changes made to the
spec, or explaining why changes aren't being made.
Note this is not always the first reply from the editor.
The Comment/Response lines can be repeated if new responses are
made presenting information that reopens the issue; however the
entire thread shouldn't be tracked, only key messages. The goal
is to minimize the effort required for someone reviewing the issues
to understand this issue and its resolution.
Changes: A reference to the diffs, or equivalently useful information
such as a link to the relevant section. Often left blank in
early-stage drafts (which have a lot of churn) or when
there's a long discussion involving multiple sets of changes
and it's therefore easier just to look at the result.
Closed: A status line on how the issue was closed. Triggers colors.
Replacing "Closed" with "Open" marks the issue unresolved.
Verified: URL to a message where the commenter indicates satisfaction
with the resolution of the issue.
(If the status was Rejected, this will turn the color green.)
It's helpful to get the commenter's feedback on the changes,
since they will often notice any mistakes. Verification
indicates full closure of the issue.
Resolved: I use this line to track by what authority the issue was closed.
It makes me think explicitly about whether the WG or anyone
else should be consulted for solutions/review/approval.
Values applicable to the CSSWG include:
Editorial - no substantive change
Bugfix - fixes an obvious error with an obvious solution
[URL] - link to WG resolution closing the issue
Editor discretion -
This is the tricky one. It's used in cases where
1. the solution isn't obvious (not Bugfix)
2. the impact of the solution is minor and localized:
* there is no cross-module impact
* there is no cross-module consistency concern
* it is unlikely to affect implementation architecture
3. no syntax/API is affected
4. there is consensus on the mailing list, at least
among the people involved in the discussion; and
nobody not involved is likely to care
It is also occasionally used to close issues as No Change
in cases where the commenter is clueless or the requested
change would clearly violate a WG design principle.
~fantasai
XXX
exit;
}
# Input/Output setup
my $outFile = $inFile;
if ($inFile =~ /\.(.+)$/) {
$outFile =~ s/\.$1/\.html/;
}
elsif ($inFile =~ /\.$/) { # tab completion case
$inFile .= 'txt' if (-e ($inFile . "txt"));
$inFile .= 'bsi' if (-e ($inFile . "bsi"));
$outFile .= 'html';
}
open IN, "<", $inFile || die "Cannot open $inFile: $!";
open OUT, ">", $outFile || die "Cannot open $outFile: $!";
$/ = "----\n";
# Header
&header;
# Issues
while (<IN>) {
chomp;
# Process headings
if (/^=/) {
s/=//g;
s/^\s+|\s+$//g ;
s/\{\s*(.+?)\s*\}//;
my $headerID;
if ($1) {
$headerID = $1;
$headerID =~ s/^#//;
}
else {
$headerID = lc;
$headerID =~ s/\s+/-/g;
}
print OUT "<h2 id=$headerID>" . $_ . "</h2>\n";
next;
}
# Don't pipe code
s/</</g;
# Linkify URLs
s/(http\S+)/<a href='\1'>\1<\/a>/g;
# Add thread links
s/>(http[s]?:\/\/lists.w3.org\/Archives\/Public\/)(\S+)<\/a>/>\1\2<\/a> <a href="https:\/\/www.w3.org\/Mail\/flatten\/index?subject=https\%3A\%2F\%2Flists.w3.org\%2FArchives\%2FPublic\%2F\2"><abbr title="Thread">∈<\/abbr><\/a>/g;
# Add mid links
s/>(http[s]?:\/\/www.w3.org\/mid\/)(\S+)<\/a>/>\1\2<\/a> <a href="mid:\2"><abbr title="Open Message">⎆<\/abbr><\/a>/g;
# Anchor issue number
s/Issue (\w+)\./Issue \1. <a href='#issue-\1'>#<\/a>/;
my $index = $1;
# Color coding WG response
my @lines = split /\n/;
my ($status, $code);
foreach (@lines) {
# Get Status
if (/^Open/) {
$status = 'open';
}
# Colorize WG response
if (/^(?:Closed|Open):\s+(\S+)/) {
$code = $statusStyle{lc $1};
$_ = '<span class="' . $code . '">' . $_ . '</span>';
}
# Colorize commenter response
elsif (/^Verified:\s+\S+/) {
$code = 'a';
$_ = '<span class="a">' . $_ . '</span>';
}
else {
$_ = '<span>' . $_ . '</span>';
}
}
# And print it
print OUT "<pre class='$status $code' id='issue-$index'>\n";
print OUT join "\n", @lines;
print OUT "</pre>\n";
}
&script;
sub header {
# Read header
local $_ = <IN>;
chomp;
# Extract title and URL
my ($title, $url, $shortname, $intro);
for (split /\n+/) {
if (/^Title:\s+(.+)$/) { $title = $1; }
elsif (/^Draft:\s+(\S+)/) { $url = $1; }
elsif (/^Shortname:\s+(\S+)/) { $shortname = $1; }
else { $intro .= $_ . "\n"; }
}
die "Error: missing document URL or title.\n" unless ($url && $title);
# Process URL to get status, date, shortname
my $status = 'Draft';
my $date = $1 if ($inFile =~ /([\d-]+)/);
if ($url =~ /([A-Z]{2})-([a-z0-9-]+)-(\d{8})/) {
$shortname = $2 unless ($shortname);
($status, $date) = ($1, $3);
$status = 'LCWD' if ('WD' eq $status && $inFile =~ /[lL][cC]/);
$date = "$1-$2-$3" if ($date =~ /(\d{4})(\d{2})(\d{2})/);
}
# Print it all out
print OUT <<XXX;
<!DOCTYPE html>
<meta charset="utf-8">
<title>$title Disposition of Comments for $date $status</title>
<style type="text/css">
pre, .legend { border: solid thin silver; padding: 0.2em; white-space: normal; }
.legend summary { font-weight: bold; }
summary { cursor: pointer; }
pre > span { display: block; white-space: pre; }
.a { background: #52E052 }
.d { background: #8CCBF2 }
.oi { background: #E0CB52 }
.r { background: orange }
.fo { background: #f66 }
pre.a { background: #E9FBE9 }
pre.d { background: #DEF }
pre.oi { background: #FCFAEE }
pre.r { background: #FFEECC }
pre.fo { background: #FBE9E9 }
.open { border: solid red; }
:target { box-shadow: 0.25em 0.25em 0.25em; }
a[href^=mid], a[href~=flatten] { text-decoration: none; }
abbr, dt { font-weight: bold; }
dl.compact { display: grid; grid-template-columns: auto 1fr; }
dt { grid-column: 1 }
dd { grid-column: 2 }
ins { color: green; }
del { color: #A00; }
</style>
<h1>$title Disposition of Comments for $date $status</h1>
<dl class="compact">
<dt>Dated Draft: <dd><a href="$url">$url</a>
<dt>Editor's Draft: <dd><a href="http://drafts.csswg.org/$shortname/">http://drafts.csswg.org/$shortname/</a>
</dl>
$intro
<details class="legend">
<summary>Disposition Status Legend and Filters</summary>
<p>The following color coding convention is used for comments:</p>
<ul>
<li class="a">Accepted or Rejected and positive response
<li class="r">Rejected and no response
<li class="fo">Rejected and negative response
<li class="d">Deferred
<li class="oi">Out-of-Scope or Invalid and not verified
</ul>
<p class=open>Open issues are marked like this</p>
<p>An issue can be closed as <code>Accepted</code>, <code>OutOfScope</code>,
<code>Invalid</code>, <code>Rejected</code>, or <code>Retracted</code>.
<code>Verified</code> indicates commentor's acceptance of the response.</p>
</details>
XXX
}
sub script {
print OUT <<XXX;
<script>
(function () {
var sheet = document.styleSheets[0];
function addCheckbox(className) {
var element = document.querySelector('*.' + className);
var span = document.createElement('span');
span.innerHTML = element.innerHTML;
element.innerHTML = null;
var check = document.createElement('input');
check.type = 'checkbox';
if (className == 'open') {
check.checked = false;
sheet.insertRule('pre:not(.open)' + '{}', sheet.cssRules.length);
check.onchange = function (e) {
rule.style.display = this.checked ? 'none' : 'block';
}
}
else {
check.checked = true;
sheet.insertRule('pre.' + className + '{}', sheet.cssRules.length);
check.onchange = function (e) {
rule.style.display = this.checked ? 'block' : 'none';
}
}
var rule = sheet.cssRules[sheet.cssRules.length - 1];
element.appendChild(check);
element.appendChild(span);
}
['a', 'd', 'fo', 'oi', 'r', 'open'].forEach(addCheckbox);
}());
</script>
XXX
}