build/data-tables/utils/generate-table.js
// see http://usability.com.au/2005/06/accessible-data-tables-2005
const fs = require('fs');
const path = require('path');
const Handlebars = require('handlebars');
const highlightLabel = require('./highlight-label');
const tableTemplate = fs.readFileSync(path.resolve(__dirname, '../templates/table.hbs'), {encoding: 'utf8'});
const _tableTemplate = Handlebars.compile(tableTemplate);
const cellTemplateDefault = fs.readFileSync(path.resolve(__dirname, '../templates/table-cell.hbs'), {encoding: 'utf8'});
const _cellTemplateDefault = Handlebars.compile(cellTemplateDefault);
const rowTemplate = fs.readFileSync(path.resolve(__dirname, '../templates/table-row.hbs'), {encoding: 'utf8'});
const _rowTemplate = Handlebars.compile(rowTemplate);
function clone(object) {
return JSON.parse(JSON.stringify(object));
}
let identCounter = 0;
module.exports = function({
group,
columns,
source,
browsers,
skipIdents,
skipExpected,
referencedNotes,
cellTemplate,
cellData,
rowData,
}) {
const _cellTemplate = cellTemplate || _cellTemplateDefault;
const rows = [];
let idents = group.idents;
if (Array.isArray(group.idents)) {
idents = {};
group.idents.forEach(ident => (idents[ident] = ident));
}
Object.keys(idents).forEach(function(ident) {
const sourceIdent = source.data[ident];
const duplicateIdent = group.duplicate[ident] && source.data[group.duplicate[ident]];
if (skipIdents && skipIdents(ident, sourceIdent, duplicateIdent)) {
return;
}
identCounter++;
const identId = group.id + '-ident-' + identCounter;
const cells = [];
if (!skipExpected) {
const expected = clone(sourceIdent.expected);
expected.platform = source.browsers.expected;
expected.groupId = group.id;
expected.identId = identId;
expected.ident = ident;
expected.notes = source.notes.getBrowser(ident, 'expected');
expected.notes.forEach(key => referencedNotes.add(String(key)));
expected.redirectTarget = source.notes.getTarget(ident, 'expected');
expected.redirectTarget && referencedNotes.add(String(expected.redirectTarget));
expected.relatedElement = source.notes.getRelated(ident, 'expected');
expected.relatedElement && referencedNotes.add(String(expected.relatedElement));
expected.isInert = !expected.browser.focusable && !expected.browser.tabbable;
cells.push(_cellTemplate(expected));
}
columns.forEach(function(browser) {
const data = clone(sourceIdent[browser]);
data.platform = source.browsers[browser];
data.groupId = group.id;
data.identId = identId;
data.ident = ident;
if (cellData) {
data.cellData = cellData(data);
}
data.notes = source.notes.getBrowser(ident, browser);
data.notes.forEach(key => referencedNotes.add(String(key)));
data.redirectTarget = source.notes.getTarget(ident, browser);
data.redirectTarget && referencedNotes.add(String(data.redirectTarget));
data.relatedElement = source.notes.getRelated(ident, browser);
data.relatedElement && referencedNotes.add(String(data.relatedElement));
data.isInert = !data.browser.focusable && !data.browser.tabbable;
cells.push(_cellTemplate(data));
});
const notes = source.notes.getIdent(ident);
notes.forEach(key => referencedNotes.add(String(key)));
const row = _rowTemplate({
groupId: group.id,
identId,
ident,
label: idents[ident],
labelHtml: highlightLabel(idents[ident], ident),
notes: notes,
rowData: rowData && rowData(ident, sourceIdent, referencedNotes) || {},
cells: cells.join('\n'),
});
rows.push(row);
});
if (!rows.length) {
return '';
}
return _tableTemplate({
summary: 'columns represent browsers, rows represent HTML elements, '
+ 'cells show whether the browser thinks the HTML element is focusable, tabbable (keyboard focusable) or inert',
caption: group.label,
expectedColumn: !skipExpected,
browsers: browsers,
groupId: group.id,
tbody: rows.join('\n'),
});
};