Step 1 — Knowledge base: perfect all reference/*.md with type, range, default, unit - text.md: add DataOrPathProps, path/data, bullet deprecated params - chart.md: add deprecated section, fix 19 params with missing elements - slide.md: add bkgd→background deprecated mapping - output.md: add masterSlide, presLayout Step 2 — Schema: align schema/presentation.schema.json with KB - Add catAxisItem and valAxisItem definitions with full sub-property constraints - Fix 7 enum constraints (barDir, displayBlanksAs, bar3DShape, etc.) - Add 4 missing fields (verbose, autoPageCharWeight, autoPageLineWeight, notes, masterSlide, presLayout) Step 3 — Translation engine: transform renderers from passthrough to validation - index.js: add normalizePosition, normalizeColor, validateEnum shared utilities - All renderers: position validation, color hex normalization, enum validation - Image: graceful failure handling (catch load errors, warn, continue) - Chart: chartType enum validation, data parity check - Table: colspan/rowspan integer validation, border array check - Full verification: basic.json and full.json generate valid PPTX Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
86 lines
3.1 KiB
JavaScript
86 lines
3.1 KiB
JavaScript
var { normalizePosition, normalizeColorInOptions, validateEnum } = require('./index');
|
|
|
|
function renderTable(slide, tableData) {
|
|
var opts = {};
|
|
if (tableData.options) {
|
|
for (var k in tableData.options) {
|
|
if (tableData.options.hasOwnProperty(k)) opts[k] = tableData.options[k];
|
|
}
|
|
}
|
|
|
|
normalizePosition(opts);
|
|
|
|
if (opts.fill && typeof opts.fill === 'object') {
|
|
normalizeColorInOptions(opts.fill, 'color');
|
|
validateEnum(opts.fill.type, ['none', 'solid'], 'fill.type');
|
|
}
|
|
|
|
if (opts.border) {
|
|
if (Array.isArray(opts.border)) {
|
|
if (opts.border.length !== 4) {
|
|
console.warn('Invalid table border array: expected 4 sides, got ' + opts.border.length);
|
|
}
|
|
} else if (typeof opts.border === 'object') {
|
|
normalizeColorInOptions(opts.border, 'color');
|
|
if (opts.border.type !== undefined) {
|
|
validateEnum(opts.border.type, ['none', 'dash', 'solid'], 'border.type');
|
|
}
|
|
}
|
|
}
|
|
|
|
var rows = [];
|
|
if (tableData.rows) {
|
|
for (var r = 0; r < tableData.rows.length; r++) {
|
|
var row = tableData.rows[r];
|
|
var newRow = [];
|
|
for (var c = 0; c < row.length; c++) {
|
|
var cell = row[c];
|
|
var newCell = { text: cell.text };
|
|
|
|
if (cell.colspan !== undefined) {
|
|
if (typeof cell.colspan !== 'number' || !isFinite(cell.colspan) || cell.colspan < 1 || cell.colspan !== Math.floor(cell.colspan)) {
|
|
console.warn('Invalid colspan: got ' + JSON.stringify(cell.colspan) + ', expected integer >= 1');
|
|
}
|
|
newCell.colspan = cell.colspan;
|
|
}
|
|
if (cell.rowspan !== undefined) {
|
|
if (typeof cell.rowspan !== 'number' || !isFinite(cell.rowspan) || cell.rowspan < 1 || cell.rowspan !== Math.floor(cell.rowspan)) {
|
|
console.warn('Invalid rowspan: got ' + JSON.stringify(cell.rowspan) + ', expected integer >= 1');
|
|
}
|
|
newCell.rowspan = cell.rowspan;
|
|
}
|
|
|
|
if (cell.options) {
|
|
newCell.options = {};
|
|
for (var k in cell.options) {
|
|
if (cell.options.hasOwnProperty(k)) newCell.options[k] = cell.options[k];
|
|
}
|
|
normalizeColorInOptions(newCell.options, 'color');
|
|
normalizeColorInOptions(newCell.options, 'highlight');
|
|
if (newCell.options.fill && typeof newCell.options.fill === 'object') {
|
|
normalizeColorInOptions(newCell.options.fill, 'color');
|
|
}
|
|
if (newCell.options.border) {
|
|
if (Array.isArray(newCell.options.border)) {
|
|
if (newCell.options.border.length !== 4) {
|
|
console.warn('Invalid cell border array: expected 4 sides, got ' + newCell.options.border.length);
|
|
}
|
|
} else if (typeof newCell.options.border === 'object') {
|
|
normalizeColorInOptions(newCell.options.border, 'color');
|
|
}
|
|
}
|
|
validateEnum(newCell.options.align, ['left', 'center', 'right', 'justify'], 'cell.align');
|
|
validateEnum(newCell.options.valign, ['top', 'middle', 'bottom'], 'cell.valign');
|
|
}
|
|
|
|
newRow.push(newCell);
|
|
}
|
|
rows.push(newRow);
|
|
}
|
|
}
|
|
|
|
slide.addTable(rows, opts);
|
|
}
|
|
|
|
module.exports = { renderTable };
|