'use strict'; /** * @typedef {import('./types').XastParent} XastParent * @typedef {import('./types').XastElement} XastElement */ const { collectStylesheet, computeStyle } = require('./style.js'); const { visit } = require('./xast.js'); const { parseSvg } = require('./parser.js'); /** * @type {(node: XastParent, id: string) => XastElement} */ const getElementById = (node, id) => { /** * @type {null | XastElement} */ let matched = null; visit(node, { element: { enter: (node) => { if (node.attributes.id === id) { matched = node; } }, }, }); if (matched == null) { throw Error('Assert node'); } return matched; }; it('collects styles', () => { const root = parseSvg(` `); const stylesheet = collectStylesheet(root); expect(computeStyle(stylesheet, getElementById(root, 'class'))).toEqual({ fill: { type: 'static', inherited: false, value: 'red' }, }); expect(computeStyle(stylesheet, getElementById(root, 'two-classes'))).toEqual( { fill: { type: 'static', inherited: false, value: 'green' }, stroke: { type: 'static', inherited: false, value: 'black' }, } ); expect(computeStyle(stylesheet, getElementById(root, 'attribute'))).toEqual({ fill: { type: 'static', inherited: false, value: 'purple' }, }); expect( computeStyle(stylesheet, getElementById(root, 'inline-style')) ).toEqual({ fill: { type: 'static', inherited: false, value: 'grey' }, }); expect(computeStyle(stylesheet, getElementById(root, 'inheritance'))).toEqual( { fill: { type: 'static', inherited: true, value: 'yellow' }, } ); expect( computeStyle(stylesheet, getElementById(root, 'nested-inheritance')) ).toEqual({ fill: { type: 'static', inherited: true, value: 'blue' }, }); }); it('prioritizes different kinds of styles', () => { const root = parseSvg(` `); const stylesheet = collectStylesheet(root); expect( computeStyle(stylesheet, getElementById(root, 'complex-selector')) ).toEqual({ fill: { type: 'static', inherited: false, value: 'red' }, }); expect( computeStyle(stylesheet, getElementById(root, 'attribute-over-inheritance')) ).toEqual({ fill: { type: 'static', inherited: false, value: 'orange' }, }); expect( computeStyle(stylesheet, getElementById(root, 'style-rule-over-attribute')) ).toEqual({ fill: { type: 'static', inherited: false, value: 'blue' }, }); expect( computeStyle( stylesheet, getElementById(root, 'inline-style-over-style-rule') ) ).toEqual({ fill: { type: 'static', inherited: false, value: 'purple' }, }); }); it('prioritizes important styles', () => { const root = parseSvg(` `); const stylesheet = collectStylesheet(root); expect( computeStyle(stylesheet, getElementById(root, 'complex-selector')) ).toEqual({ fill: { type: 'static', inherited: false, value: 'green' }, }); expect( computeStyle( stylesheet, getElementById(root, 'style-rule-over-inline-style') ) ).toEqual({ fill: { type: 'static', inherited: false, value: 'green' }, }); expect( computeStyle( stylesheet, getElementById(root, 'inline-style-over-style-rule') ) ).toEqual({ fill: { type: 'static', inherited: false, value: 'purple' }, }); }); it('treats at-rules and pseudo-classes as dynamic styles', () => { const root = parseSvg(` `); const stylesheet = collectStylesheet(root); expect(computeStyle(stylesheet, getElementById(root, 'media-query'))).toEqual( { fill: { type: 'dynamic', inherited: false }, } ); expect(computeStyle(stylesheet, getElementById(root, 'hover'))).toEqual({ fill: { type: 'dynamic', inherited: false }, }); expect(computeStyle(stylesheet, getElementById(root, 'inherited'))).toEqual({ fill: { type: 'dynamic', inherited: true }, }); expect( computeStyle(stylesheet, getElementById(root, 'inherited-overriden')) ).toEqual({ fill: { type: 'static', inherited: false, value: 'blue' }, }); expect(computeStyle(stylesheet, getElementById(root, 'static'))).toEqual({ fill: { type: 'static', inherited: false, value: 'black' }, }); }); it('considers `); const stylesheet = collectStylesheet(root); expect(computeStyle(stylesheet, getElementById(root, 'media-query'))).toEqual( { fill: { type: 'dynamic', inherited: false }, } ); expect( computeStyle(stylesheet, getElementById(root, 'kinda-static')) ).toEqual({ fill: { type: 'dynamic', inherited: false }, }); expect(computeStyle(stylesheet, getElementById(root, 'static'))).toEqual({ fill: { type: 'static', inherited: false, value: 'blue' }, }); }); it('ignores `); const stylesheet = collectStylesheet(root); expect(computeStyle(stylesheet, getElementById(root, 'valid-type'))).toEqual({ fill: { type: 'static', inherited: false, value: 'red' }, }); expect(computeStyle(stylesheet, getElementById(root, 'empty-type'))).toEqual({ fill: { type: 'static', inherited: false, value: 'green' }, }); expect( computeStyle(stylesheet, getElementById(root, 'invalid-type')) ).toEqual({}); }); it('ignores keyframes atrule', () => { const root = parseSvg(` `); const stylesheet = collectStylesheet(root); expect(computeStyle(stylesheet, getElementById(root, 'element'))).toEqual({ animation: { type: 'static', inherited: false, value: 'loading 4s linear infinite', }, }); });