Skip to content

Commit

Permalink
load content styles for rich text component
Browse files Browse the repository at this point in the history
  • Loading branch information
yavorsk committed Nov 30, 2023
1 parent b252e97 commit de5e93a
Show file tree
Hide file tree
Showing 6 changed files with 458 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { SitecorePageProps } from 'lib/page-props';
import { getContentStylesheetLink } from '@sitecore-jss/sitecore-jss-nextjs';
import { Plugin } from '..';

class ContentStylesPlugin implements Plugin {
order = 2;

async exec(props: SitecorePageProps) {
// Get content stylessheet link, empty if styles are not used on the page
const contentStyles = getContentStylesheetLink(props.layoutData);

contentStyles && props.headLinks.push(contentStyles);

return props;
}
}

export const contentStylesPlugin = new ContentStylesPlugin();
1 change: 1 addition & 0 deletions packages/sitecore-jss-nextjs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export {
RenderingType,
EDITING_COMPONENT_PLACEHOLDER,
EDITING_COMPONENT_ID,
getContentStylesheetLink,
} from '@sitecore-jss/sitecore-jss/layout';
export { mediaApi } from '@sitecore-jss/sitecore-jss/media';
export {
Expand Down
1 change: 1 addition & 0 deletions packages/sitecore-jss-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export {
EditButtonTypes,
} from '@sitecore-jss/sitecore-jss/utils';
export {
getContentStylesheetLink,
LayoutService,
LayoutServiceData,
LayoutServicePageState,
Expand Down
346 changes: 346 additions & 0 deletions packages/sitecore-jss/src/layout/content-styles.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,346 @@
/* eslint-disable no-unused-expressions */
import { expect } from 'chai';
import {
traverseField,
traverseComponent,
getContentStylesheetUrl,
traversePlaceholder,
getContentStylesheetLink,
} from './content-styles';
import { ComponentRendering, Field, HtmlElementRendering, Item, LayoutServiceData } from './models';

export const PAGES_SERVER_URL = 'https://pages-assets.sitecorecloud.io';

describe('content-styles', () => {
const truthyValue = { value: '<div class="test bar"><p class="foo ck-content">bar</p></div>' };
const falsyValue = { value: '<div class="test bar"><p class="foo">ck-content</p></div>' };

describe('getContentStylesheetLink', () => {
it('should return null when route data is empty', () => {
expect(getContentStylesheetLink({ sitecore: { context: {}, route: null } })).to.be.null;
});

it('should set "loadStyles: false" when layout does not have a ck-content class', () => {
const layoutData: LayoutServiceData = {
sitecore: {
context: {},
route: {
name: 'route',
placeholders: {
car: [{ componentName: 'foo', fields: { car: falsyValue } }],
},
},
},
};

expect(getContentStylesheetLink(layoutData)).to.be.null;
});

it('should set "loadStyles: true" when layout has a ck-content class', () => {
const layoutData: LayoutServiceData = {
sitecore: {
context: {},
route: {
name: 'route',
placeholders: {
car: [
{
componentName: 'foo',
fields: { car: falsyValue },
placeholders: {
bar: [{ componentName: 'cow', fields: { dog: truthyValue } }],
},
},
],
},
},
},
};

expect(getContentStylesheetLink(layoutData)).to.deep.equal({
href: `${PAGES_SERVER_URL}/pages/styles/content-styles.min.css`,
rel: 'stylesheet',
});
});
});

describe('traverseField', () => {
describe('Field', () => {
it('should set "loadStyles: false" when field does not have a ck-content class', () => {
const config = { loadStyles: false };
const field: Field = {
value: '<div class="test bar"><p class="foo">ck-content</p></div>',
};

traverseField(field, config);

expect(config.loadStyles).to.be.false;
});

it('should set "loadStyles: true" when field has a ck-content class', () => {
const config = { loadStyles: false };
const field: Field = {
value: '<div class="test bar"><p class="foo ck-content">bar</p></div>',
};

traverseField(field, config);

expect(config.loadStyles).to.be.true;
});
});

describe('Item', () => {
it('should set "loadStyles: false" when field does not have a ck-content class', () => {
const config = { loadStyles: false };
const field: Item = {
name: 'test',
fields: {
richText: {
value: '<div class="test bar"><p class="foo">ck-content</p></div>',
},
},
};

traverseField(field, config);

expect(config.loadStyles).to.be.false;
});

it('should set "loadStyles: true" when field has a ck-content class', () => {
const config = { loadStyles: false };
const field: Item = {
name: 'test',
fields: {
richText: {
value: '<div class="test bar"><p class="foo ck-content">bar</p></div>',
},
},
};

traverseField(field, config);

expect(config.loadStyles).to.be.true;
});
});

describe('Item[]', () => {
it('should set "loadStyles: false" when field does not have a ck-content class', () => {
const config = { loadStyles: false };
const field: Item[] = [
{
name: 'test',
fields: {
richText: {
value: '<div class="test bar"><p class="foo">ck-content</p></div>',
},
},
},
];

traverseField(field, config);

expect(config.loadStyles).to.be.false;
});

it('should set "loadStyles: true" when field has a ck-content class', () => {
const config = { loadStyles: false };
const field: Item[] = [
{
name: 'test',
fields: {
richText: {
value: '<div class="test bar"><p class="foo ck-content">bar</p></div>',
},
},
},
];

traverseField(field, config);

expect(config.loadStyles).to.be.true;
});
});

describe('editing', () => {
it('should set "loadStyles: false" when field does not have a ck-content class', () => {
const config = { loadStyles: false };
const field: Field = {
value: '',
editable: falsyValue.value,
};

traverseField(field, config);

expect(config.loadStyles).to.be.false;
});

it('should set "loadStyles: true" when field has a ck-content class', () => {
const config = { loadStyles: false };
const field: Field = {
value: '',
editable: truthyValue.value,
};

traverseField(field, config);

expect(config.loadStyles).to.be.true;
});
});

it('should skip when field is undefined', () => {
const config = { loadStyles: false };
const field = undefined;

traverseField(field, config);

expect(config.loadStyles).to.be.false;
});

it('should skip when loadStyles is true', () => {
const config = { loadStyles: true };
const field = falsyValue;

traverseField(field, config);

expect(config.loadStyles).to.be.true;
});
});

describe('traverseComponent', () => {
it('should skip when loadStyles is true', () => {
const config = { loadStyles: true };
const component = {
componentName: 'ContentBlock',
fields: {
richText: falsyValue,
},
};

traverseComponent(component, config);

expect(config.loadStyles).to.be.true;
});

it('should set "loadStyles: false" when component does not have a ck-content class', () => {
const config = { loadStyles: false };
const component = {
componentName: 'ContentBlock',
fields: {
richText: falsyValue,
},
placeholders: {
foo: [{ componentName: 'fooComponent', fields: { car: falsyValue } }],
},
};

traverseComponent(component, config);

expect(config.loadStyles).to.be.false;
});

it('should set "loadStyles: true" when component has a ck-content class', () => {
const config = { loadStyles: false };
const component = {
componentName: 'ContentBlock',
fields: {
richText: falsyValue,
},
placeholders: {
foo: [{ componentName: 'fooComponent', fields: { car: truthyValue } }],
},
};

traverseComponent(component, config);

expect(config.loadStyles).to.be.true;
});
});

describe('traversePlaceholder', () => {
it('should skip when loadStyles is true', () => {
const config = { loadStyles: true };
const components = [
{
componentName: 'ContentBlock',
fields: {
richText: falsyValue,
},
},
];

traversePlaceholder(components, config);

expect(config.loadStyles).to.be.true;
});

it('should set "loadStyles: false" when placeholder does not have a ck-content class', () => {
const config = { loadStyles: false };
const components: (ComponentRendering | HtmlElementRendering)[] = [
{
componentName: 'ContentBlock',
fields: {
richText: falsyValue,
},
placeholders: {
foo: [{ componentName: 'foo', fields: { car: falsyValue } }],
},
},
{
componentName: 'Foo',
fields: {
car: falsyValue,
},
placeholders: {
body: [{ componentName: 'foo', fields: { car: falsyValue } }],
},
},
];

traversePlaceholder(components, config);

expect(config.loadStyles).to.be.false;
});

it('should set "loadStyles: true" when component has a ck-content class', () => {
const config = { loadStyles: false };
const components: (ComponentRendering | HtmlElementRendering)[] = [
{
componentName: 'ContentBlock',
fields: {
richText: falsyValue,
},
placeholders: {
foo: [{ componentName: 'foo', fields: { car: falsyValue } }],
},
},
{
componentName: 'Foo',
fields: {
car: falsyValue,
},
placeholders: {
body: [{ componentName: 'foo', fields: { car: truthyValue } }],
},
},
];

traversePlaceholder(components, config);

expect(config.loadStyles).to.be.true;
});
});

describe('getContentStylesheetUrl', () => {
it('should return the default url', () => {
expect(getContentStylesheetUrl()).to.equal(
`${PAGES_SERVER_URL}/pages/styles/content-styles.min.css`
);
});

it('should return the custom url', () => {
expect(getContentStylesheetUrl('https://foo.bar')).to.equal(
'https://foo.bar/pages/styles/content-styles.min.css'
);
});
});
});
Loading

0 comments on commit de5e93a

Please sign in to comment.