diff options
| author | Ralph Amissah <ralph.amissah@gmail.com> | 2026-09-13 20:53:26 -0400 |
|---|---|---|
| committer | Ralph Amissah <ralph.amissah@gmail.com> | 2026-09-14 12:18:51 -0400 |
| commit | 6835275408e1629f450d163e0cc5221c977e87d2 (patch) | |
| tree | ac35771a889a4766d8efc89af5f78e91fa99e3d3 /org/out_sqlite.org | |
| parent | regex: 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.org | 81 |
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; } |
