ecmarkup
Version:
Custom element definitions and core utilities for markup that specifies ECMAScript and related technologies.
166 lines (165 loc) • 7.03 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const Clause_1 = require("./Clause");
const header_parser_1 = require("./header-parser");
const type_parser_1 = require("./type-parser");
const utils_1 = require("./utils");
const Figure_1 = require("./Figure");
class Table extends Figure_1.default {
constructor(spec, node, table, tableType) {
let of = null;
if (tableType === 'abstract methods') {
of = node.getAttribute('of');
if (of) {
if (!node.getAttribute('caption')) {
node.setAttribute('caption', `Abstract Methods of ${of}`);
}
}
else {
spec.warn({
type: 'node',
ruleId: 'emu-abstract-methods-invalid',
message: `<emu-table type="abstract methods"> must have an 'of' attribute`,
node,
});
tableType = null;
}
}
super(spec, node);
this.of = null;
this.table = table;
this.tableType = tableType;
this.of = of;
this.methods = new Map();
if (tableType === 'abstract methods') {
this.processAbstractMethodsDeclarations();
this.defineInnerBiblioEntries();
}
}
processAbstractMethodsDeclarations() {
const { spec, table } = this;
const tbody = table.querySelector('tbody');
for (const tr of tbody.children) {
if (tr.childElementCount < 2) {
spec.warn({
type: 'node',
ruleId: 'emu-abstract-methods-invalid',
message: `<emu-table type="abstract methods"> <tr>s must contain at least two <td>s`,
node: tr,
});
continue;
}
let header = tr.firstElementChild;
const headerFirstChild = (0, utils_1.traverseWhile)(header.firstChild, 'nextSibling', el => { var _a; return ((_a = el.textContent) === null || _a === void 0 ? void 0 : _a.trim()) === ''; });
if ((headerFirstChild === null || headerFirstChild === void 0 ? void 0 : headerFirstChild.nodeName) === 'DEL') {
header = (0, utils_1.traverseWhile)(headerFirstChild, 'nextElementSibling', node => node.nodeName === 'DEL');
if (!header)
continue;
}
else if ((headerFirstChild === null || headerFirstChild === void 0 ? void 0 : headerFirstChild.nodeName) === 'INS') {
header = headerFirstChild;
}
if (header.nodeName !== 'TD' && header.nodeName !== 'INS') {
this.spec.warn({
type: 'node',
ruleId: 'missing-header',
message: `could not locate header element; found <${header.tagName.toLowerCase()}>`,
node: header,
});
continue;
}
const headerSource = (0, Clause_1.getHeaderSource)(header, spec);
const parseResult = (0, header_parser_1.parseHeader)(headerSource);
if (parseResult.type === 'failure') {
(0, header_parser_1.warnAllErrors)(spec, header, parseResult);
continue;
}
let signature;
try {
signature = (0, Clause_1.parsedHeaderToSignature)(parseResult);
}
catch (e) {
if (e instanceof type_parser_1.ParseError) {
const { line, column } = (0, utils_1.offsetToLineAndColumn)(headerSource, e.offset);
spec.warn({
type: 'contents',
ruleId: 'type-parsing',
message: e.message,
node: header,
nodeRelativeLine: line,
nodeRelativeColumn: column,
});
continue;
}
else {
throw e;
}
}
const rowId = tr.id || undefined;
if (tbody.children.length > 1 && !rowId) {
spec.warn({
type: 'node',
ruleId: 'abstract-method-id',
message: '<tr>s which define abstract methods should have their own id',
node: tr,
});
}
this.methods.set(parseResult.name, { signature, rowId });
const { name, formattedHeader, formattedParams, formattedReturnType } = (0, header_parser_1.formatHeader)(spec, header, parseResult);
if (formattedHeader !== null)
header.innerHTML = formattedHeader;
const para = spec.doc.createElement('p');
let paraText = `The abstract method ${name} takes ${formattedParams} and returns ${formattedReturnType}.`;
if (header.nodeName === 'INS')
paraText = `<ins>${paraText}</ins>`;
para.innerHTML = paraText;
tr.children[1].insertBefore(para, tr.children[1].firstChild);
}
}
defineInnerBiblioEntries() {
for (const [name, info] of this.methods) {
const { signature, rowId } = info;
const biblioEntry = {
type: 'op',
kind: 'abstract method',
aoid: name,
id: rowId,
refId: this.id,
signature,
effects: [],
};
this.spec.biblio.add(biblioEntry, this.spec.namespace);
}
}
static async enter({ spec, node }) {
let tableType = node.getAttribute('type');
if (tableType && tableType !== 'abstract methods') {
spec.warn({
type: 'node',
ruleId: 'emu-table-invalid-type',
message: `<emu-table> has invalid type "${tableType}"`,
node,
});
tableType = null;
}
let tableEl = (0, utils_1.traverseWhile)(node.firstElementChild, 'nextElementSibling', el => el.nodeName === 'EMU-CAPTION' || (el.nodeName === 'SPAN' && el.textContent === ''));
if (!tableEl || tableEl.nodeName !== 'TABLE') {
if (tableType) {
spec.warn({
type: 'node',
ruleId: 'emu-table-missing',
message: `<emu-table type="${tableType}"> must contain a <table> element`,
node,
});
tableType = null;
}
else {
tableEl = spec.doc.createElement('table');
}
}
const table = new Table(spec, node, tableEl, tableType === 'abstract methods' ? 'abstract methods' : null);
Figure_1.default.injectFigureElement(spec, node, table);
}
}
Table.elements = ['EMU-TABLE'];
exports.default = Table;