import { collectStylesheet, computeStyle } from './style.js';
import { visit } from './xast.js';
import { parseSvg } from './parser.js';
/**
* @param {import('./types.js').XastParent} node
* @param {string} id
* @returns {import('./types.js').XastElement}
*/
const getElementById = (node, id) => {
/** @type {?import('./types.js').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'))).toStrictEqual(
{
fill: { type: 'static', inherited: false, value: 'red' },
},
);
expect(
computeStyle(stylesheet, getElementById(root, 'two-classes')),
).toStrictEqual({
fill: { type: 'static', inherited: false, value: 'green' },
stroke: { type: 'static', inherited: false, value: 'black' },
});
expect(
computeStyle(stylesheet, getElementById(root, 'attribute')),
).toStrictEqual({
fill: { type: 'static', inherited: false, value: 'purple' },
});
expect(
computeStyle(stylesheet, getElementById(root, 'inline-style')),
).toStrictEqual({
fill: { type: 'static', inherited: false, value: 'grey' },
});
expect(
computeStyle(stylesheet, getElementById(root, 'inheritance')),
).toStrictEqual({
fill: { type: 'static', inherited: true, value: 'yellow' },
});
expect(
computeStyle(stylesheet, getElementById(root, 'nested-inheritance')),
).toStrictEqual({
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')),
).toStrictEqual({
fill: { type: 'static', inherited: false, value: 'red' },
});
expect(
computeStyle(stylesheet, getElementById(root, 'override-selector')),
).toStrictEqual({
fill: { type: 'static', inherited: false, value: 'blue' },
});
expect(
computeStyle(
stylesheet,
getElementById(root, 'attribute-over-inheritance'),
),
).toStrictEqual({
fill: { type: 'static', inherited: false, value: 'orange' },
});
expect(
computeStyle(stylesheet, getElementById(root, 'style-rule-over-attribute')),
).toStrictEqual({
fill: { type: 'static', inherited: false, value: 'blue' },
});
expect(
computeStyle(
stylesheet,
getElementById(root, 'inline-style-over-style-rule'),
),
).toStrictEqual({
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')),
).toStrictEqual({
fill: { type: 'static', inherited: false, value: 'green' },
});
expect(
computeStyle(
stylesheet,
getElementById(root, 'style-rule-over-inline-style'),
),
).toStrictEqual({
fill: { type: 'static', inherited: false, value: 'green' },
});
expect(
computeStyle(
stylesheet,
getElementById(root, 'inline-style-over-style-rule'),
),
).toStrictEqual({
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')),
).toStrictEqual({
fill: { type: 'dynamic', inherited: false },
});
expect(computeStyle(stylesheet, getElementById(root, 'hover'))).toStrictEqual(
{
fill: { type: 'dynamic', inherited: false },
},
);
expect(
computeStyle(stylesheet, getElementById(root, 'inherited')),
).toStrictEqual({
fill: { type: 'dynamic', inherited: true },
});
expect(
computeStyle(stylesheet, getElementById(root, 'inherited-overridden')),
).toStrictEqual({
fill: { type: 'static', inherited: false, value: 'blue' },
});
expect(
computeStyle(stylesheet, getElementById(root, 'static')),
).toStrictEqual({
fill: { type: 'static', inherited: false, value: 'black' },
});
});
it('considers
`);
const stylesheet = collectStylesheet(root);
expect(
computeStyle(stylesheet, getElementById(root, 'media-query')),
).toStrictEqual({
fill: { type: 'dynamic', inherited: false },
});
expect(
computeStyle(stylesheet, getElementById(root, 'kinda-static')),
).toStrictEqual({
fill: { type: 'dynamic', inherited: false },
});
expect(
computeStyle(stylesheet, getElementById(root, 'static')),
).toStrictEqual({
fill: { type: 'static', inherited: false, value: 'blue' },
});
});
it('ignores
`);
const stylesheet = collectStylesheet(root);
expect(
computeStyle(stylesheet, getElementById(root, 'valid-type')),
).toStrictEqual({
fill: { type: 'static', inherited: false, value: 'red' },
});
expect(
computeStyle(stylesheet, getElementById(root, 'empty-type')),
).toStrictEqual({
fill: { type: 'static', inherited: false, value: 'green' },
});
expect(
computeStyle(stylesheet, getElementById(root, 'invalid-type')),
).toStrictEqual({});
});
it('ignores keyframes atrule', () => {
const root = parseSvg(`
`);
const stylesheet = collectStylesheet(root);
expect(
computeStyle(stylesheet, getElementById(root, 'element')),
).toStrictEqual({
animation: {
type: 'static',
inherited: false,
value: 'loading 4s linear infinite',
},
});
});
it('ignores @-webkit-keyframes atrule', () => {
const root = parseSvg(`
`);
const stylesheet = collectStylesheet(root);
expect(
computeStyle(stylesheet, getElementById(root, 'element')),
).toStrictEqual({
animation: {
type: 'static',
inherited: false,
value: 'loading 4s linear infinite',
},
});
});
it('ignores @-moz-keyframes atrule', () => {
const root = parseSvg(`
`);
const stylesheet = collectStylesheet(root);
expect(
computeStyle(stylesheet, getElementById(root, 'element')),
).toStrictEqual({
animation: {
type: 'static',
inherited: false,
value: 'loading 4s linear infinite',
},
});
});
it('ignores @-o-keyframes atrule', () => {
const root = parseSvg(`
`);
const stylesheet = collectStylesheet(root);
expect(
computeStyle(stylesheet, getElementById(root, 'element')),
).toStrictEqual({
animation: {
type: 'static',
inherited: false,
value: 'loading 4s linear infinite',
},
});
});