// ============================================================ // SLIDE PRIMITIVES // ============================================================ // What a model may draw when the named layouts have no word for what was asked. // Everything here is about what the validator refuses: a shape arriving from a // model is untrusted input that ends up in a file somebody downloads. const test = require('node:test'); const assert = require('node:assert'); const fs = require('fs'); const path = require('path'); const shapes = require('../src/utils/slideShapes'); const read = p => fs.readFileSync(path.join(__dirname, '..', p), 'utf8'); const one = spec => shapes.normalise([spec])[0]; test('a shape is positioned in percentages, and never off the slide', () => { // A model reasons about "left half" far better than about EMU. const clamped = one({ kind: 'rect', x: 95, y: 90, w: 30, h: 40, fill: 'FFFFFF' }); assert.equal(clamped.x, 95); assert.equal(clamped.w, 5, 'width is cut to the slide edge, not drawn past it'); assert.equal(clamped.h, 10); // Nonsense coordinates fall back rather than becoming NaN in the renderer. const junk = one({ kind: 'rect', x: 'left', y: null, w: undefined, h: 'big', fill: 'FFFFFF' }); assert.equal(junk.x, 5); assert.equal(junk.w, 30); }); test('colours are six hex digits or nothing at all', () => { assert.equal(one({ kind: 'rect', fill: '#eff6ff' }).fill, 'EFF6FF', 'a leading # and case are tolerated'); // The easiest place for a model to put something that is not a colour. for (const bad of ['red', 'rgb(1,2,3)', '#fff', 'EFF6F', 'EFF6FFF', '