Skip to content

Commit

Permalink
Generate HTML5 instead of HTML 4.01
Browse files Browse the repository at this point in the history
- Use HTML5 DOCTYPE.
- Use CSS to style tables instead of obsolete HTML attributes.
- Use `id` attributes instead of `name`. Sanitize the values of all such
  attributes (and corresponding URLs using them) so that they don't
  contain spaces.
- Do not create duplicate `id` attributes in index pages that aren't
  sorted by section.
- Postprocess issues to replace obsolete `<tt>` elements with `<code>`.

There are validation errors for some of the issues themselves, due to
the use of `<p/>` as a paragraph break, which is not correct HTML5.
Paragraphs should start with `<p>` and end with `</p>`, not just be
started implictly and then separated by `<p/>`.

Wrong:

	This is paragraph one.
	<p/>
	This is paragraph two.

Also wrong:

	<p>
	This is paragraph one.
	<p/>
	This is paragraph two.
	</p>

Right:

	<p>
	This is paragraph one.
	</p>
	<p>
	This is paragraph two.
	</p>
  • Loading branch information
jwakely committed Jan 25, 2024
1 parent 9dcdcb0 commit 6c3fea6
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 48 deletions.
5 changes: 2 additions & 3 deletions bin/issues_to_be_moved.sh
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,8 @@ dump_issues()
}

cat <<EOT
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>C++ Standard Library Issues to be moved in $meeting</title>
Expand Down
7 changes: 7 additions & 0 deletions src/issues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ auto lwg::parse_issue_from_file(std::string tx, std::string const & filename,
}
};

// <tt> is obsolete in HTML5, replace with <code>:
for (auto p = tx.find("<tt"); p != tx.npos; p = tx.find("<tt", p+5))
if (tx.at(p+3) == '>' || tx.at(p+3) == ' ')
tx.replace(p, 3, "<code");
for (auto p = tx.find("</tt>"); p != tx.npos; p = tx.find("</tt>", p+7))
tx.replace(p, 5, "</code>");

issue is;

// Get issue number
Expand Down
104 changes: 64 additions & 40 deletions src/report_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ struct order_by_priority {
std::reference_wrapper<lwg::section_map> section_db;
};

// Replace spaces to make a string usable as an 'id' attribute,
// or as an URL fragment (#foo) that links to an 'id' attribute.
inline std::string spaces_to_underscores(std::string s) {
std::replace(s.begin(), s.end(), ' ', '_');
return s;
}


auto major_section(lwg::section_num const & sn) -> std::string {
std::string const prefix{sn.prefix};
Expand Down Expand Up @@ -162,13 +169,12 @@ void print_list(std::ostream & out, Container const & source, char const * separ

void print_file_header(std::ostream& out, std::string const & title) {
out <<
R"(<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
R"(<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>)" << title << R"(</title>
<style type="text/css">
<style>
p {text-align:justify}
li {text-align:justify}
blockquote.note
Expand All @@ -181,7 +187,17 @@ R"(<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
}
ins {background-color:#A0FFA0}
del {background-color:#FFA0A0}
table {border-collapse: collapse;}
table.issues-index { border: 1px solid; border-collapse: collapse; }
table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
table.issues-index td { padding: 4px; border: 1px solid; }
table.issues-index td:nth-child(1) { text-align: right; }
table.issues-index td:nth-child(2) { text-align: left; }
table.issues-index td:nth-child(3) { text-align: left; }
table.issues-index td:nth-child(4) { text-align: left; }
table.issues-index td:nth-child(5) { text-align: center; }
table.issues-index td:nth-child(6) { text-align: center; }
table.issues-index td:nth-child(7) { text-align: left; }
table.issues-index td:nth-child(5) span.no-pr { color: red; }
@media (prefers-color-scheme: dark) {
html {
color: #ddd;
Expand Down Expand Up @@ -218,21 +234,21 @@ void print_file_trailer(std::ostream& out) {
}


void print_table(std::ostream& out, std::vector<lwg::issue>::const_iterator i, std::vector<lwg::issue>::const_iterator e, lwg::section_map & section_db) {
void print_table(std::ostream& out, std::vector<lwg::issue>::const_iterator i, std::vector<lwg::issue>::const_iterator e, lwg::section_map& section_db, bool link_stable_names = false) {
#if defined (DEBUG_LOGGING)
std::cout << "\t" << std::distance(i,e) << " items to add to table" << std::endl;
#endif

out <<
R"(<table border="1" cellpadding="4">
R"(<table class="issues-index">
<tr>
<td align="center"><a href="lwg-toc.html"><b>Issue</b></a></td>
<td align="center"><a href="lwg-status.html"><b>Status</b></a></td>
<td align="center"><a href="lwg-index.html"><b>Section</b></a></td>
<td align="center"><b>Title</b></td>
<td align="center"><b>Proposed Resolution</b></td>
<td align="center"><a href="unresolved-prioritized.html"><b>Priority</b></a></td>
<td align="center"><b>Duplicates</b></td>
<th><a href="lwg-toc.html">Issue</a></th>
<th><a href="lwg-status.html">Status</a></th>
<th><a href="lwg-index.html">Section</a></th>
<th>Title</th>
<th>Proposed Resolution</th>
<th><a href="unresolved-prioritized.html">Priority</a></th>
<th>Duplicates</th>
</tr>
)";

Expand All @@ -241,45 +257,46 @@ R"(<table border="1" cellpadding="4">
out << "<tr>\n";

// Number
out << "<td align=\"right\">" << make_html_anchor(*i)
out << "<td id=\"" << i->num << "\">" << make_html_anchor(*i)
<< "<sup><a href=\"https://cplusplus.github.io/LWG/issue" << i->num
<< "\">(i)</a></sup></td>\n";

// Status
out << "<td align=\"left\"><a href=\"lwg-active.html#" << lwg::remove_qualifier(i->stat) << "\">" << i->stat << "</a><a name=\"" << i->num << "\"></a></td>\n";
const auto status_idattr = spaces_to_underscores(std::string(lwg::remove_qualifier(i->stat)));
out << "<td><a href=\"lwg-active.html#" << status_idattr << "\">" << i->stat << "</a></td>\n";

// Section
out << "<td align=\"left\">";
out << "<td>";
assert(!i->tags.empty());
out << section_db[i->tags[0]] << " " << i->tags[0];
if (i->tags[0] != prev_tag) {
if (link_stable_names && i->tags[0] != prev_tag) {
prev_tag = i->tags[0];
out << "<a name=\"" << as_string(prev_tag) << "\"></a>";
out << "<a id=\"" << as_string(prev_tag) << "\"></a>";
}
out << "</td>\n";

// Title
out << "<td align=\"left\">" << i->title << "</td>\n";
out << "<td>" << i->title << "</td>\n";

// Has Proposed Resolution
out << "<td align=\"center\">";
out << "<td>";
if (i->has_resolution) {
out << "Yes";
}
else {
out << "<font color=\"red\">No</font>";
out << "<span class=\"no-pr\">No</span>";
}
out << "</td>\n";

// Priority
out << "<td align=\"center\">";
out << "<td>";
if (i->priority != 99) {
out << i->priority;
}
out << "</td>\n";

// Duplicates
out << "<td align=\"left\">";
out << "<td>";
print_list(out, i->duplicates, ", ");
out << "</td>\n"
<< "</tr>\n";
Expand All @@ -297,21 +314,23 @@ void print_issue(std::ostream & out, lwg::issue const & iss, lwg::section_map &
issue_set_by_first_tag const & active_issues, print_issue_type type = print_issue_type::in_list) {
out << "<hr>\n";

const auto status_idattr = spaces_to_underscores(std::string(lwg::remove_qualifier(iss.stat)));

// Number

// When printing for the list, also emit an absolute link to the individual file.
// Absolute link so that copying only the big lists elsewhere doesn't result in broken links.
if(type == print_issue_type::in_list) {
out << "<h3><a name=\"" << iss.num << "\" href=\"#" << iss.num << "\">" << iss.num << "</a>";
out << "<h3 id=\"" << iss.num << "\"><a href=\"#" << iss.num << "\">" << iss.num << "</a>";
out << "<sup><a href=\"https://cplusplus.github.io/LWG/issue" << iss.num << "\">" << "(i)</a></sup>";
}
else {
out << "<p><em>This page is a snapshot from the LWG issues list, see the "
"<a href=\"lwg-active.html\">Library Active Issues List</a> "
"for more information and the meaning of "
"<a href=\"lwg-active.html#" << lwg::remove_qualifier(iss.stat) << "\">"
"<a href=\"lwg-active.html#" << status_idattr << "\">"
<< iss.stat << "</a> status.</em></p>\n";
out << "<h3><a name=\"" << iss.num << "\" href=\"" << lwg::filename_for_status(iss.stat) << '#' << iss.num << "\">" << iss.num << "</a>";
out << "<h3 id=\"" << iss.num << "\"><a href=\"" << lwg::filename_for_status(iss.stat) << '#' << iss.num << "\">" << iss.num << "</a>";
}

// Title
Expand All @@ -324,7 +343,7 @@ void print_issue(std::ostream & out, lwg::issue const & iss, lwg::section_map &
out << ", " << lwg::format_section_tag_as_link(section_db, iss.tags[k]);
}

out << " <b>Status:</b> <a href=\"lwg-active.html#" << lwg::remove_qualifier(iss.stat) << "\">" << iss.stat << "</a>\n";
out << " <b>Status:</b> <a href=\"lwg-active.html#" << status_idattr << "\">" << iss.stat << "</a>\n";
out << " <b>Submitter:</b> " << iss.submitter
<< " <b>Opened:</b> ";
print_date(out, iss.date);
Expand Down Expand Up @@ -405,7 +424,7 @@ void print_resolutions(std::ostream & out, std::vector<lwg::issue> const & issue
out << "<hr>\n"

// Number and title
<< "<h3><a name=\"" << iss.num << "\"></a>" << iss.num << ". " << iss.title << "</h3>\n"
<< "<h3 id=\"" << iss.num << "\">" << iss.num << ". " << iss.title << "</h3>\n"

// text
<< iss.resolution << "\n\n";
Expand Down Expand Up @@ -474,7 +493,7 @@ void report_generator::make_active(std::vector<issue> const & issues, fs::path c
print_paper_heading(out, "active", lwg_issues_xml);
out << lwg_issues_xml.get_intro("active") << '\n';
out << "<h2 id='History'>Revision History</h2>\n" << lwg_issues_xml.get_revisions(issues, diff_report) << '\n';
out << "<h2><a name=\"Status\"></a>Issue Status</h2>\n" << lwg_issues_xml.get_statuses() << '\n';
out << "<h2 id='Status'>Issue Status</h2>\n" << lwg_issues_xml.get_statuses() << '\n';
out << "<h2 id='Issues'>Active Issues</h2>\n";
print_issues(out, issues, section_db, [](issue const & i) {return is_active(i.stat);} );
print_file_trailer(out);
Expand Down Expand Up @@ -528,7 +547,7 @@ void report_generator::make_tentative(std::vector<issue> const & issues, fs::pat
// print_paper_heading(out, "active", lwg_issues_xml);
// out << lwg_issues_xml.get_intro("active") << '\n';
// out << "<h2>Revision History</h2>\n" << lwg_issues_xml.get_revisions(issues) << '\n';
// out << "<h2><a name=\"Status\"></a>Issue Status</h2>\n" << lwg_issues_xml.get_statuses() << '\n';
// out << "<h2 id='Status'>Issue Status</h2>\n" << lwg_issues_xml.get_statuses() << '\n';
out << "<p>" << build_timestamp << "</p>";
out << "<h2>Tentative Issues</h2>\n";
print_issues(out, issues, section_db, [](issue const & i) {return is_tentative(i.stat);} );
Expand All @@ -548,7 +567,7 @@ void report_generator::make_unresolved(std::vector<issue> const & issues, fs::pa
// print_paper_heading(out, "active", lwg_issues_xml);
// out << lwg_issues_xml.get_intro("active") << '\n';
// out << "<h2>Revision History</h2>\n" << lwg_issues_xml.get_revisions(issues) << '\n';
// out << "<h2><a name=\"Status\"></a>Issue Status</h2>\n" << lwg_issues_xml.get_statuses() << '\n';
// out << "<h2 id='Status'></a>Issue Status</h2>\n" << lwg_issues_xml.get_statuses() << '\n';
out << "<p>" << build_timestamp << "</p>";
out << "<h2>Unresolved Issues</h2>\n";
print_issues(out, issues, section_db, [](issue const & i) {return is_not_resolved(i.stat);} );
Expand Down Expand Up @@ -675,7 +694,8 @@ R"(<h1>C++ Standard Library Issues List (Revision )" << lwg_issues_xml.get_revis
<h1>Table of Contents</h1>
<p>Reference )" << is14882_docno << R"(</p>
<p>This document is the Table of Contents for the <a href="lwg-active.html">Library Active Issues List</a>,
<a href="lwg-defects.html">Library Defect Reports and Accepted Issues</a>, and <a href="lwg-closed.html">Library Closed Issues List</a>.</p>
<a href="lwg-defects.html">Library Defect Reports and Accepted Issues</a>, and <a href="lwg-closed.html">Library Closed Issues List</a>,
sorted by priority.</p>
)";
out << "<p>" << build_timestamp << "</p>";

Expand All @@ -684,7 +704,7 @@ R"(<h1>C++ Standard Library Issues List (Revision )" << lwg_issues_xml.get_revis
for (auto i = issues.cbegin(), e = issues.cend(); i != e;) {
int px = i->priority;
auto j = std::find_if(i, e, [&](issue const & iss){ return iss.priority != px; } );
out << "<h2><a name=\"Priority " << px << "\"</a>";
out << "<h2 id=\"Priority_" << px << "\">";
if (px == 99) {
out << "Not Prioritized";
}
Expand Down Expand Up @@ -725,8 +745,10 @@ This document is the Index by Status and Section for the <a href="lwg-active.htm

for (auto i = issues.cbegin(), e = issues.cend(); i != e;) {
auto const & current_status = i->stat;
auto idattr = current_status;
std::replace(idattr.begin(), idattr.end(), ' ', '_');
auto j = std::find_if(i, e, [&](issue const & iss){ return iss.stat != current_status; } );
out << "<h2><a name=\"" << current_status << "\"</a>" << current_status << " (" << (j-i) << " issues)</h2>\n";
out << "<h2 id=\"" << idattr << "\">" << current_status << " (" << (j-i) << " issues)</h2>\n";
print_table(out, i, j, section_db);
i = j;
}
Expand Down Expand Up @@ -759,8 +781,9 @@ This document is the Index by Status and Date for the <a href="lwg-active.html">

for (auto i = issues.cbegin(), e = issues.cend(); i != e;) {
std::string const & current_status = i->stat;
auto const idattr = spaces_to_underscores(current_status);
auto j = find_if(i, e, [&](issue const & iss){ return iss.stat != current_status; } );
out << "<h2><a name=\"" << current_status << "\"</a>" << current_status << " (" << (j-i) << " issues)</h2>\n";
out << "<h2 id=\"" << idattr << "\">" << current_status << " (" << (j-i) << " issues)</h2>\n";
print_table(out, i, j, section_db);
i = j;
}
Expand Down Expand Up @@ -826,15 +849,16 @@ void report_generator::make_sort_by_section(std::vector<issue>& issues, fs::path
}
}
std::string const msn{major_section(section_db[i->tags[0]])};
out << "<h2><a name=\"Section " << msn << "\"></a>" << "Section " << msn << " (" << (j-i) << " issues)</h2>\n";
auto idattr = spaces_to_underscores(msn);
out << "<h2 id=\"Section_" << idattr << "\">" << "Section " << msn << " (" << (j-i) << " issues)</h2>\n";
if (active_only) {
out << "<p><a href=\"lwg-index.html#Section " << msn << "\">(view all issues)</a></p>\n";
out << "<p><a href=\"lwg-index.html#Section_" << idattr << "\">(view all issues)</a></p>\n";
}
else if (mjr_section_open.count(*i) > 0) {
out << "<p><a href=\"lwg-index-open.html#Section " << msn << "\">(view only non-Ready open issues)</a></p>\n";
out << "<p><a href=\"lwg-index-open.html#Section_" << idattr << "\">(view only non-Ready open issues)</a></p>\n";
}

print_table(out, i, j, section_db);
print_table(out, i, j, section_db, true);
i = j;
}

Expand Down
10 changes: 5 additions & 5 deletions xml/lwg-issues.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1393,7 +1393,7 @@ ownership of it.
<p><b><a name="NAD">NAD</a></b> - The LWG has reached consensus that
the issue is not a defect in the Standard.</p>

<p><b><a name="NAD Editorial">NAD Editorial</a></b> - The LWG has reached consensus that
<p><b><a id="NAD_Editorial">NAD Editorial</a></b> - The LWG has reached consensus that
the issue can either be handled editorially, or is handled by a paper (usually
linked to in the rationale).</p>

Expand All @@ -1412,13 +1412,13 @@ ownership of it.

<p>The following statuses have been retired, but may show up on older issues lists.</p>

<p><b><a name="NAD Future">NAD Future</a></b> - In addition to the regular status, the
<p><b><a name="NAD_Future">NAD Future</a></b> - In addition to the regular status, the
LWG believes that this issue should be revisited at the next revision of the standard.
That is now an ongoing task managed by the Library Evolution Working Group, and most
issues in this status were reopended with the status <a href="#NAD Editorial">LEWG</a>.
issues in this status were reopended with the status <a href="#NAD_Editorial">LEWG</a>.
</p>

<p><b><a name="NAD Concepts">NAD Concepts</a></b> - This status reflects an evolution
<p><b><a id="NAD_Concepts">NAD Concepts</a></b> - This status reflects an evolution
of the language during the development of C++11, where a new feature entered the
language, called <i>concepts</i>, that fundamentally changed the way templates would
be specified and written. While this language feature was removed towards the end of
Expand All @@ -1428,7 +1428,7 @@ ownership of it.
the concepts feature. All such issues have been closed with this status, and may be
revisitted should this or a similar language feature return for a future standard.</p>

<p><b><a name="NAD Arrays">NAD Arrays</a></b> - This status reflects an evolution
<p><b><a id="NAD_Arrays">NAD Arrays</a></b> - This status reflects an evolution
of the language during the development of C++14/17, where work on a Technical
Specification, called the <i>Arrays TS</i> was begun. In early 2016, this work was
abandoned, and the work item was officially withdrawn. During development of the TS,
Expand Down

0 comments on commit 6c3fea6

Please sign in to comment.