aboutsummaryrefslogtreecommitdiffhomepage
path: root/org/out_sqlite.org
diff options
context:
space:
mode:
authorRalph Amissah <ralph.amissah@gmail.com>2026-09-13 20:53:26 -0400
committerRalph Amissah <ralph.amissah@gmail.com>2026-09-14 12:18:51 -0400
commit6835275408e1629f450d163e0cc5221c977e87d2 (patch)
treeac35771a889a4766d8efc89af5f78e91fa99e3d3 /org/out_sqlite.org
parentregex: confine url within an endnote (delimiter) (diff)
epub and html: no errors left over the sample set
epubcheck 5.3.0 over the 35 sample epubs went from 1302 remaining errors to none. The six causes for those remaining errors fixed here. most of the count was one of them: - Tables (1123 errors, 86%) where the writer emitted obsolete attributes, removed in 2014; table also now in div instead of a paragraph. also fixed: - Navigation (115). Every level 4 heading's nav entry ended "#0", the ocn of an object that has no ocn and so no id. - Duplicate ids (37). (from three unrelated sources). - The publication identifier (27 warnings). dc:identifier was a hardcoded hex string, not a UUID, and the same one in all 35 files, so two documents in one library collided. It is now UUID v5 over the document's own uid: a real RFC 4122 identifier, stable across builds and distinct per document. - Image manifest entries (15). media-type was "image/" plus the file extension, giving "image/jpg", which is not a media type; epubcheck reads it as a foreign resource and wants a fallback. There is now a mapping, which also covers svg and webp. Item ids came from the file basename, and "2bits_02_01-100.png" gave an id starting with a digit, which is not an XML name; ids are now prefixed and sanitised. - An ocn resolving to no segment (9). A poem block and its first verse share one ocn; the verses are written into a segment and the block itself is not. Also dropped from the package document: an xmlns:xsi that nothing used, and a prefix declaration for the rendition vocabulary, which is a reserved prefix and needed no declaring. The package now carries xml:lang. test-epub-validity.sh now allows no fatal and no error. Two NAV-011 warnings remain and are described in it. Three reference .ssp files change, all of them the anchor tag disambiguation above. (assisted by Claude-Code)
Diffstat (limited to 'org/out_sqlite.org')
-rw-r--r--org/out_sqlite.org81
1 files changed, 52 insertions, 29 deletions
diff --git a/org/out_sqlite.org b/org/out_sqlite.org
index 2895b72..a9f1065 100644
--- a/org/out_sqlite.org
+++ b/org/out_sqlite.org
@@ -1268,35 +1268,58 @@ string html_table(M,O)(
string[] _table_cols;
string _table;
string _tablenote;
+ bool _in_head = false;
+ bool _in_body = false;
foreach(row_idx, row; _table_rows) {
_table_cols = row.split(rgx.table_delimiter_col);
- _table ~= "<tr>";
- foreach(col_idx, cell; _table_cols) {
- if ((_table_cols.length == 1)
- && (_table_rows.length <= row_idx+2)) { // check row_idx+2 (rather than == ++row_idx)
- _tablenote ~= cell;
- } else {
- string _col_is = (row_idx == 0 && obj.table.heading) ? "th" : "td";
- string _align = ("style=\"text-align:"
- ~ ((obj.table.column_aligns[col_idx] == "l")
- ? "left\"" : "right\""));
- _table ~= "<"
- ~ _col_is
- ~ " width=\""
- ~ obj.table.column_widths[col_idx].to!string
- ~ "%\" "
- ~ _align
- ~ ">";
- _table ~= cell;
- _table ~= "</"
- ~ _col_is
- ~ ">";
- }
- }
- _table ~= "</tr>";
+ if ((_table_cols.length == 1)
+ && (_table_rows.length <= row_idx+2)) { // check row_idx+2 (rather than == ++row_idx)
+ _tablenote ~= _table_cols[0];
+ continue;
+ }
+ /+ ↓ a heading row goes in <thead>, the rest in <tbody> +/
+ if (row_idx == 0 && obj.table.heading) {
+ _table ~= "<thead>";
+ _in_head = true;
+ } else if (!_in_body) {
+ if (_in_head) { _table ~= "</thead>"; _in_head = false; }
+ _table ~= "<tbody>";
+ _in_body = true;
+ }
+ _table ~= "<tr>";
+ foreach(col_idx, cell; _table_cols) {
+ bool _is_th = (row_idx == 0 && obj.table.heading);
+ string _col_is = _is_th ? "th" : "td";
+ string _class = (col_idx < obj.table.column_aligns.length
+ && obj.table.column_aligns[col_idx] == "l") ? "left" : "right";
+ _table ~= "<"
+ ~ _col_is
+ ~ (_is_th ? " scope=\"col\"" : "")
+ ~ " class=\""
+ ~ _class
+ ~ "\">";
+ _table ~= cell;
+ _table ~= "</"
+ ~ _col_is
+ ~ ">";
}
+ _table ~= "</tr>";
+ }
+ if (_in_head) { _table ~= "</thead>"; }
+ else if (_in_body) { _table ~= "</tbody>"; }
+ /+ ↓ column widths as a <colgroup>, not a width attribute on every cell +/
+ string _colgroup;
+ if (obj.table.column_widths.length > 0) {
+ string _cols;
+ foreach(w; obj.table.column_widths) {
+ _cols ~= (w > 0)
+ ? "<col style=\"width:" ~ w.to!string ~ "%\" />"
+ : "<col />";
+ }
+ _colgroup = "<colgroup>" ~ _cols ~ "</colgroup>";
+ }
Tuple!(string, string) t = tuple(
- _table,
+ (_colgroup ~ _table),
_tablenote,
);
return t;
@@ -1305,15 +1328,15 @@ string html_table(M,O)(
Tuple!(string, string) t = _tablarize(obj, _txt);
_txt = t[0];
string _note = t[1];
- string o = format(q"┃<p class="%s">
- <table summary="normal text css" width="95%%" border="0" cellpadding="2" align="center">
+ string o = format(q"┃<div class="%s">
+ <table class="table">
%s
</table>
%s
- </p>┃",
+ </div>┃",
obj.metainfo.is_a,
_txt,
- _note
+ (_note.strip.empty) ? "" : ("<p class=\"tablenote\">" ~ _note.strip ~ "</p>")
);
return o;
}