06b9de0132c8653afc3c2d91cbc386c2f3967e72 lrnassar Tue Apr 28 12:05:20 2026 -0700 QA cleanup of /docs/ landing page and staticPage.lua writer. refs #36894 docs/index.md: fix /docs/contacts.html -> /contacts.html (was 404), correct "Hubs Basics" -> "Hub Basics", drop stray "?" in fragment-only URLs (/cgi-bin/hgHubConnect?#hubDeveloper etc.), convert section headings to sentence case per GB convention, rewrite tutorial-table descriptions in a consistent imperative voice, and replace the fragmented "Checked using our hub development tools" bullet with "Validate your hub with our hub development tools". docs/staticPage.lua: extend Link() to add target="_blank" rel="noopener" on http(s):// absolute URLs, and stop emitting empty title='' on every link. Modernize Table() output to drop deprecated HTML4 attributes: <col width="X%"> -> <col style="width: X%">, and align="left|right|center" on <th>/<td> replaced with style="text-align: ..." (omitted for the default left alignment). Renames html_align() -> html_align_style() to reflect the new return value. diff --git docs/staticPage.lua docs/staticPage.lua index 3fc86255de3..615beda2a3d 100644 --- docs/staticPage.lua +++ docs/staticPage.lua @@ -208,43 +208,51 @@ return '<del>' .. s .. '</del>' end function obfuscate(s) -- obfuscate the email address a la Hiram's encodeEmail.pl local refs = {} for i = 1, string.len(s) do local ascCode = string.byte(s, i) local ref = "&#" .. tostring(ascCode) table.insert(refs, ref) end return table.concat(refs, "") end function Link(s, src, tit, attr) + local extra = "" if string.sub(src, 1, 7)=="mailto:" then src = "mailto:" .. obfuscate(string.sub(src, 7), 7) -- assume that the link label is an email address if it contains an @ character if string.match(s, "%@")~=nil then s = obfuscate(s) end else + -- absolute URLs open in a new tab; rel="noopener" prevents tabnabbing + if string.match(src, "^https?://") then + extra = " target='_blank' rel='noopener'" + end src = escape(src, true) tit = escape(tit, true) end + if tit and tit ~= "" then + extra = extra .. " title='" .. tit .. "'" + end - return "<a href='" .. src .. "' title='" .. tit .. "'>" .. s .. "</a>" + return "<a href='" .. src .. "'" .. extra .. ">" .. s .. "</a>" end function Image(s, src, tit, attr) return "<img alt='" .. escape(s,true) .. "' src='" .. escape(src,true) .. "' title='" .. escape(tit,true) .. "'/>" end function Code(s, attr) return "<code" .. attributes(attr) .. ">" .. escape(s) .. "</code>" end function InlineMath(s) return "\\(" .. escape(s) .. "\\)" @@ -358,89 +366,87 @@ return "<ol>\n" .. table.concat(buffer, "\n") .. "\n</ol>" end -- Revisit association list STackValue instance. function DefinitionList(items) local buffer = {} for _,item in pairs(items) do for k, v in pairs(item) do table.insert(buffer,"<dt>" .. k .. "</dt>\n<dd>" .. table.concat(v,"</dd>\n<dd>") .. "</dd>") end end return "<dl>\n" .. table.concat(buffer, "\n") .. "\n</dl>" end --- Convert pandoc alignment to something HTML can use. --- align is AlignLeft, AlignRight, AlignCenter, or AlignDefault. -function html_align(align) - if align == 'AlignLeft' then - return 'left' - elseif align == 'AlignRight' then - return 'right' +-- Convert pandoc alignment into a style attribute fragment for HTML5. +-- align is AlignLeft, AlignRight, AlignCenter, or AlignDefault. Left is the +-- default cell alignment, so emit nothing in that case. +function html_align_style(align) + if align == 'AlignRight' then + return ' style="text-align: right"' elseif align == 'AlignCenter' then - return 'center' + return ' style="text-align: center"' else - return 'left' + return '' end end function CaptionedImage(src, tit, caption) return '<div class="figure">\n<img src="' .. escape(src,true) .. '" title="' .. escape(tit,true) .. '"/>\n' .. '<p class="caption">' .. caption .. '</p>\n</div>' end -- Caption is a string, aligns is an array of strings, -- widths is an array of floats, headers is an array of -- strings, rows is an array of arrays of strings. function Table(caption, aligns, widths, headers, rows) local buffer = {} local function add(s) table.insert(buffer, s) end add("<table>") if caption ~= "" then add("<caption>" .. caption .. "</caption>") end if widths and widths[1] ~= 0 then for _, w in pairs(widths) do - add('<col width="' .. string.format("%.0f%%", w * 100) .. '" />') + add('<col style="width: ' .. string.format("%.0f%%", w * 100) .. '">') end end local header_row = {} local empty_header = true for i, h in pairs(headers) do - local align = html_align(aligns[i]) - table.insert(header_row,'<th align="' .. align .. '">' .. h .. '</th>') + table.insert(header_row,'<th' .. html_align_style(aligns[i]) .. '>' .. h .. '</th>') empty_header = empty_header and h == "" end if empty_header then head = "" else add('<tr class="header">') for _,h in pairs(header_row) do add(h) end add('</tr>') end local class = "even" for _, row in pairs(rows) do class = (class == "even" and "odd") or "even" add('<tr class="' .. class .. '">') for i,c in pairs(row) do - add('<td align="' .. html_align(aligns[i]) .. '">' .. c .. '</td>') + add('<td' .. html_align_style(aligns[i]) .. '>' .. c .. '</td>') end add('</tr>') end add('</table>') return table.concat(buffer,'\n') end function RawInline(format, str) if format == "html" then return str else --- not sure what to do here for PDF or ebook output... --- return str end end