-
Notifications
You must be signed in to change notification settings - Fork 0
Design Reference
This chapter acts as a reference for design creation. It covers all from specification to templating and assets management. Be aware, that this chapter does not cover the template features in detail. If you want to know more about templating, we refer to the BSI CX design documentation. For a quick overview about what features you can use in which version of BSI CX you can checkout the feature matrix.
One mandatory and very important artifact in a design ZIP file is the design.json
file (or design.properties
in the
legacy format). To generate a design.json
trough this build, you have to place a design.js
file in your template
root folder. This has to be a CommonJS module, exporting an object in the required structure.
Here you have two options: Creating the structure by hand or using the builder classes. We recommend you to use the builder classes, because you have IntelliSense support while writing your code and don't have to know the exact names of all properties.
To create builder objects, you can use the cx
factory object. Just require the cx
constant and use the properties to
create new builder instances of all types.
The design object specifies the whole design: What content element groups and elements are available, what styles can be used, what editor configs are available, and many more. Take a look at the following example:
const {cx, Locale} = require('@bsi-cx/design-build');
module.exports = cx.design
.withTitle('BSI Landingpage')
.withAuthor('John Doe')
.withDate('18.08.2021')
.withPreviewImage(require('./preview.png'))
.withDefaultLocale(Locale.EN)
.withLocales(
Locale.EN,
Locale.DE,
Locale.DE_DE,
Locale.DE_CH)
.withContentElementGroups(
cx.contentElementGroup
.withGroupId('content')
.withLabel('Content')
.withContentElements(
require('./content-elements/content/title'),
require('./content-elements/content/text')))
.withStyleConfigs(
require('./styles/background-color'),
require('./styles/text-color'))
.withHtmlEditorConfigs(
require('./html-editor-configs/full'),
require('./html-editor-configs/normal'))
.withNLS(...require('./nls'));
Since this is proper JavaScript you can take full advantage of all language features. For example, it is a good idea to
split your design specification into several files and stack them together using require(file)
. So it's recommended to
create a separate folder for each content element, containing the specification, the template, stylesheets and possible
other element specific assets.
Use the cx
builder factory to create a new content element group builder objects:
module.exports = cx.contentElementGroup
.withGroupId('content')
.withLabel('Inhalt')
.withContentElements(
require('./content-elements/content/title'),
require('./content-elements/content/text'));
Use the cx
builder factory to create new content element builder objects:
require('./styles.less');
const {cx, Icon} = require('@bsi-cx/design-build');
module.exports = cx.contentElement
.withElementId('content-title')
.withIcon(Icon.HEADING)
.withLabel('Title')
.withFile(require('./template.hbs.twig'))
.withParts(
cx.part.plainText
.withLabel('Title'));
You can also create content element part builder objects using the cx.part
factory. Take a look at the following
example:
const {cx, Icon} = require('@bsi-cx/design-build');
module.exports = cx.contentElement
.withElementId('content-image-with-text')
.withIcon(Icon.HEADING)
.withLabel('Image with Text')
.withFile(require('./template.twig'))
.withParts(
cx.part.image
.withLabel('Image'),
cx.part.plainText
.withLabel('Text'));
Be aware, that the part definitions have to be in the same order they appear in the template markup. In large and
complex elements, this can be very tricky. To solve this problem, you can give a unique identifier to each part. Set the
identifier with the withId(id)
method and use the same identifier as value in the data-bsi-element-part
attribute in
your template. It's strongly recommended using a UUID as unique identifier. You can always create new UUIDs
using duckduckgo.com or any other UUID generator. Take a look at the following
example:
const {cx, Icon} = require('@bsi-cx/design-build');
module.exports = cx.contentElement
.withElementId('content-teaser')
.withIcon(Icon.HEADING)
.withLabel('Teaser')
.withFile(require('./template.hbs.twig'))
.withParts(
cx.part.formattedText
.withId('22235837-cf9e-49e9-8918-294b22e2854d')
.withLabel('Text')
.withHtmlEditorConfig(full),
cx.part.plainText
.withId('6849e817-c96d-42aa-a0a8-0d2f2410197e')
.withLabel('Subtitle'),
cx.part.plainText
.withId('cc246a71-e563-412b-9a7e-9c3fc0475f2e')
.withLabel('Title'));
The corresponding template to the code snippet above would look like this:
<section data-bsi-element="content-teaser" class="element content-teaser">
<h1 data-bsi-element-part="cc246a71-e563-412b-9a7e-9c3fc0475f2e">
Lorem ipsum dolor sit amet
</h1>
<h2 data-bsi-element-part="6849e817-c96d-42aa-a0a8-0d2f2410197e">
Vestibulum pulvinar ex eget magna porttitor
</h2>
<div data-bsi-element-part="22235837-cf9e-49e9-8918-294b22e2854d">
Pellentesque iaculis ornare rhoncus. Proin id iaculis odio, id euismod elit.
</div>
</section>
The rendered template in the design ZIP would then look like this:
<section data-bsi-element="content-teaser" class="element content-teaser">
<h1 data-bsi-element-part="plain-text">
Lorem ipsum dolor sit amet
</h1>
<h2 data-bsi-element-part="plain-text">
Vestibulum pulvinar ex eget magna porttitor
</h2>
<div data-bsi-element-part="formatted-text">
Pellentesque iaculis ornare rhoncus. Proin id iaculis odio, id euismod elit.
</div>
</section>
In case you hava to use a custom/non-standard or project specific content element part, use a raw part:
const {cx} = require('@bsi-cx/design-build');
module.exports = cx.contentElement
.withElementId('chart')
.withLabel('Chart')
.withFile(require('./template.twig'))
.withParts(
cx.part.plainText
.withId('6849e817-c96d-42aa-a0a8-0d2f2410197e')
.withLabel('Subtitle'),
cx.part.raw('chart')
.withId('22235837-cf9e-49e9-8918-294b22e2854d')
.withLabel('Chart')
.withProperty('type', 'pie')
.withProperty('data', [24, 32, 42]));
You can pass your own properties by using the withProperty(name, value)
method. The value must be
JSON serializable.
Dropzones can be specified on design level and on content element level. Dropzones inside includes will be specified on
design level. To define a dropzone inside your template, it's sufficient to place a data-bsi-dropzone
attribute
containing a UUID:
<div data-bsi-dropzone="93a899b6-4435-4399-b352-61e347f79038">
{% include '../../title/h1/template.twig' %}
</div>
Regardless the level this dropzone is placed, you can always use the .withDropzones(...dropzones)
method on the
current builder object:
.withDropzones(
cx.dropzone
.withDropzone('93a899b6-4435-4399-b352-61e347f79038')
.withMaxAllowedElements(1) // this is optional
.withCopyAllowed(false) // this is optional
.withAllowedElements(
require('./content-elements/title/h1'),
require('./content-elements/content/text')))
The data-bsi-dropzone-*
attributes will be placed and filled automatically during the build.
When you are using one of our web or email starter templates, you might want to add further elements to an existing
dropzone. This can be done by using the withExtendedDropzone(id, ...elements)
method on the design, content element
and include builder objects:
.withExtendedDropzone(
'93a899b6-4435-4399-b352-61e347f79038', // this is the ID of the dropzone you like to extend
require('./content-elements/title/h1'), // these elements will be appended to the list of allowed elements
require('./content-elements/content/text'))
You can create style configuration builder objects using the cx.style
factory. For the corresponding CSS class objects
you can use the cx.cssClass
factory:
const {cx} = require('@bsi-cx/design-build');
module.exports = cx.style
.withIdentifier('background-color')
.withLabel('Background Color')
.withCssClasses(
cx.cssClass
.withLabel('Black')
.withCssClass('black-background'),
cx.cssClass
.withLabel('Blue')
.withCssClass('blue-background'),
cx.cssClass
.withLabel('Red')
.withCssClass('red-background'),
cx.cssClass
.withLabel('White')
.withCssClass('white-background'));
There is also a shortcut available to create a style configuration. The above configuration could be simplified using
the cx.h
helper factory:
const {cx} = require('@bsi-cx/design-build');
module.exports = cx.h.style(
'background-color',
'Background Color',
cx.h.cssClass('black-background','Black'),
cx.h.cssClass('blue-background','Blue'),
cx.h.cssClass('red-background','Red'),
cx.h.cssClass('white-background','White'));
To apply a style configuration to a content element, just use the withStyleConfigs(...styleConfigs)
method on the
content element builder object:
const {cx, Icon} = require('@bsi-cx/design-build');
module.exports = cx.contentElement
.withElementId('content-title')
.withIcon(Icon.HEADING)
.withLabel('Title')
.withStyleConfigs(
require('../../../styles/text-color'),
require('../../../styles/background-color'))
.withFile(require('./template.hbs.twig'))
.withParts(
cx.part.plainText
.withLabel('Title'));
You can define a HTML editor configuration for the formatted-text
content element part by using the
cx.htmlEditorConfig
factory:
const {EnterMode, Feature, Format, FontSizeUnit, cx} = require('@bsi-cx/design-build');
module.exports = cx.htmlEditorConfig
.withIdentifier('extended')
.withFeatures(
Feature.BOLD,
Feature.ITALIC,
Feature.UNDERLINE,
Feature.STRIKE_THROUGH,
Feature.SUBSCRIPT,
Feature.SUPERSCRIPT,
Feature.FONT_SIZE,
Feature.LINE_HEIGHT,
Feature.TEXT_COLOR,
Feature.BACKGROUND_COLOR,
Feature.ALIGN_LEFT,
Feature.ALIGN_CENTER,
Feature.ALIGN_RIGHT,
Feature.ALIGN_JUSTIFY,
Feature.FORMAT_OL,
Feature.FORMAT_UL,
Feature.OUTDENT,
Feature.INDENT,
Feature.PARAGRAPH_FORMAT,
Feature.QUOTE,
Feature.SPECIAL_CHARACTERS,
Feature.EMOTICONS,
Feature.INSERT_LINK)
.withTextColors('#0082a1', '#bb9f84', '#fe9915', '#ffffff', '#666666')
.withBackgroundColors('#0082a1', '#bb9f84', '#fe9915', '#ffffff', '#666666')
.withFormats(Format.P, Format.H1, Format.H2, Format.H3, Format.H4, Format.H5, Format.H6, Format.PRE)
.withFontSizes(8, 9, 10, 11, 12, 14, 16, 18, 24, 30, 36, 48, 72)
.withFontSizeUnit(FontSizeUnit.PX)
.withFontSizeDefault(16)
.withLineHeights(1, 1.15, 1.5, 2)
.withEnterMode(EnterMode.P);
To apply the configuration to a formatted-text
content element part, you can use the withHtmlEditorConfig(config)
method on the desired content element part builder object:
const {Icon, cx} = require('@bsi-cx/design-build');
module.exports = cx.contentElement
.withElementId('Text')
.withIcon(Icon.TEXT)
.withLabel('Text')
.withFile(require('./template.hbs.twig'))
.withParts(
cx.part.formattedText
.withLabel('Text')
.withHtmlEditorConfig(require('../../../html-editor-configs/extended')));
The following example illustrates how you can configure a website:
const {cx} = require('@bsi-cx/design-build');
module.exports = cx.design
// ...
.withWebsite(
cx.website
.withMaxNavigationLevel(2)
.withIncludes(
cx.pageInclude
.withName('Template for new content')
.withEditable(true)
.withFile(require('./includes/page.html')),
cx.include
.withIdentifier('footer')
.withName('Footer')
.withEditable(true)
.withFile(require('./includes/footer.twig')),
cx.include
.withIdentifier('header')
.withName('Header')
.withEditable(true)
.withFile(require('./includes/header.twig')),
cx.include
.withIdentifier('navigation')
.withName('Navigation')
.withEditable(false)
.withFile(require('./includes/navigation.hbs'))))
// ...
If you want to translate certain aspects of your design, you must specify some NLS objects. See the following example for details:
const {cx, Locale} = require('@bsi-cx/design-build');
module.exports = [
cx.nls
.withIdentifier('action')
.withTranslations(
cx.translation
.withLocale(Locale.WILDCARD)
.withTranslation('Action'),
cx.translation
.withLocale(Locale.DE)
.withTranslation('Aktion')),
cx.nls
.withIdentifier('banner')
.withTranslations(
cx.translation
.withLocale(Locale.WILDCARD)
.withTranslation('Please support our friends!'),
cx.translation
.withLocale(Locale.DE)
.withTranslation('Bitte unterstütze unsere Freunde!'))
];
There is also a cx.h
shortcut available for faster and simpler NLS object creation:
const {cx, Locale} = require('@bsi-cx/design-build');
module.exports = [
cx.h.nls(
'action',
cx.h.t('action'),
cx.h.t('de', 'Aktion'),
cx.h.t(Locale.DE_CH, 'Aktion')),
cx.h.nls(
'contact',
cx.h.t('contact'),
cx.h.t('de', 'Kontakt'),
cx.h.t(Locale.DE_CH, 'Kontakt'))
];
It is recommended to outsource your NLS array to a separate Java Script file. However, you may find it too complicated to define your translations using Java Script. Sure you can also use JSON (or a CommonJS module, exporting an equivalent object) for this:
{
"action": {
"*": "Action",
"de": "Aktion"
}
}
Once you have written your translation file, you must register it in your design builder object:
const {cx, Locale} = require('@bsi-cx/design-build');
module.exports = cx.design
.withDefaultLocale(Locale.EN)
.withLocales(
Locale.EN,
Locale.DE,
Locale.DE_DE,
Locale.DE_CH)
// ...
.withNLS(...require('./nls')); // register Java Script NLS definitions (mind the spread operator ...)
If you defined your translations as JSON or plain Java Script object, you have to register them as raw value:
const {cx, Locale} = require('@bsi-cx/design-build');
module.exports = cx.design
.withDefaultLocale(Locale.EN)
.withLocales(
Locale.EN,
Locale.DE,
Locale.DE_DE,
Locale.DE_CH)
// ...
.withRawNLS(require('./nls')); // register plain NLS definitions (no spread operator required)
Most of the with...
methods also have a withRaw...
pendant. Using the raw method allows you to set a property
without the use of any builder objects. This may can be useful if you want to use custom or bleeding edge features.
Be aware, that if you decide to set a raw value, you can't use any builder objects inside the structure of that
raw value (a workaround for this would be invoking the build()
method on the nested builder object).
The following example illustrates the use of raw values for styles and HTML editor configurations:
const {Icon, cx} = require('@bsi-cx/design-build');
module.exports = cx.contentElement
.withElementId('Text')
.withIcon(Icon.TEXT)
.withLabel('Text')
.withFile(require('./template.hbs.twig'))
.withRawStyleConfigs('background-color','text-color')
.withParts(
cx.part.formattedText
.withLabel('Text')
.withRawHtmlEditorConfig('full'));
Be aware, that you also must register your style and HTML editor configurations in the design specification builder object:
const {cx} = require('@bsi-cx/design-build');
module.exports = cx.design
// ...
.withStyleConfigs(
require('./styles/background-color'),
require('./styles/text-color'))
.withHtmlEditorConfigs(
require('./html-editor-configs/full'))
// ...
Some features of CX are introduced in later versions and not all features are available in all design types.
The design build can exclude incompatible features automatically, but you can also specify compatible versions and
design types for your template manually. To do so, use the withMinVersion(version)
, withMaxVersion(version)
and
withAllowedTypes(...types)
builder methods:
const {cx, Version, DesignType} = require('@bsi-cx/design-build');
module.exports = cx.contentElement
// ...
.withMinVersion(Version.CX_1_3)
.withMaxVersion(Version.CX_22_0) // max version is not mandatory
.withAllowedTypes(DesignType.WEBSITE)
// ...
If you have to implement more complex logic regarding the current target version or design type,
you can use the Version.TARGET
and DesignType.TARGET
constants:
const {Version, DesignType} = require('@bsi-cx/design-build');
if(Version.TARGET >= Version.CX_1_3 && DesignType.TARGET === DesignType.WEBSITE) {
// do something when target version is >= CX 1.3 and design type is website
} else {
// do something else
}
You can also check for the target version and design type inside your Twig templates:
{% if cx.version.TARGET >= cx.version.CX_1_3 and cx.design.TARGET == cx.design.WEBSITE %}
{# ... #}
{% endif %}
The current target version is available as cx.version.TARGET
.
To compare the version, use the constants from cx.version
: STUDIO_1_0
, STUDIO_1_1
, STUDIO_1_2
, CX_1_3
and CX_22_0
.
Besides, the versions are also printable:
<p>Built for BSI CX {{ cx.version.TARGET.toString() }}</p>
The current target design type is available as cx.design.TARGET
.
To compare the design type, use the constants from cx.design
: WEBSITE
, LANDINGPAGE
and EMAIL
.
To parameterize your design build, it is possible to pass properties to your underlying design. The properties will be available inside your stylesheets (Less, Sass), Twig templates and template definitions during the build process. The properties file itself is a simple CommonJS module, exporting a plain Java Script object with keys and values. The values can also be nested objects.
const {css} = require('@bsi-cx/design-build');
module.exports = {
build: Date.now(),
contact: require('./contact'),
styles: {
secondaryColor: css.color('#abc'),
primaryColor: '#ff00ff',
background: css.url(__dirname, 'content-elements', 'content', 'title', 'placeholder.png'),
foreground: css.dataUri(__dirname, 'content-elements', 'content', 'title', 'placeholder.png'),
flag: true,
margin: css.number('10px')
}
};
Since Webpack does not interpret the properties file it's not possible to import assets with require. You have to
use the css
helper functions to do so. Besides, using the helper functions has other advantages:
- You can describe what kind of property this is (color, url, numeric value with dimension).
- Because the helper functions return an object you can access the stored value in different formats.
- You can use Less and Sass functions to modify color and numeric values.
To access the properties within your templates you need to use the properties
object:
<div style="background-image: {{ properties.styles.background }}"></div>
Within your stylesheets, you need to use the bsiProperty
accessor function:
$flag: bsiProperty('styles.flag');
@if $flag {
.element.content-text {
color: #ff00ff;
content: bsiProperty('styles.secondaryColor');
background: bsiProperty('styles.background');
margin: bsiProperty('styles.margin');
}
}
@margin: bsiProperty('styles.margin');
.element.content-title {
> h2 {
background-color: bsiProperty('styles.secondaryColor')
}
background: bsiProperty('styles.background') repeat-x;
margin: @margin;
}
It is considered good practice to store the accessed property's value in a variable instead of inlining the
bsiProperty
function call.
The bsiProperty
function also accepts a fallback value as a second parameter.
If you don't provide a fallback value and the property does not exist in the properties model, an error will occur during the design build.
$color: bsiProperty('unknown', #f0f);
@color: bsiProperty('unknown', #f0f);
Since there is no bsiProperty
accessor function for Twig templates, you simply use the ternary operator:
{% set color = properties.unknown ?: '#ff00ff' %}
It is also possible to use the bsiProperty
function inside your template definition JavaScript files:
const {cx, Locale, bsiProperty} = require('@bsi-cx/design-build');
const author = bsiProperty('author');
const date = bsiProperty('date');
module.exports = cx.design
.withTitle('BSI Landingpage')
.withAuthor(author)
.withDate(date)
.withPreviewImage(require('./preview.png'))
.withDefaultLocale(Locale.EN)
.withLocales(Locale.EN)
.withContentElementGroups(
cx.contentElementGroup
.withGroupId('content')
.withLabel('Content')
.withContentElements(...require('./content-elements/content')));
To define a property as a color value, use css.color
helper:
const {css} = require('@bsi-cx/design-build');
module.exports = {
primaryColor: css.color('#ff00ff'), // standard hex encoding
secondaryColor: css.color('#abc'), // shorthand hex encoding
tertiaryColor: css.color('#ff00ffaa'), // hex encoding with additonal alpha channel
backgroundColor: css.color('rgb(255,128,0)'), // RGB encoding
backgroundColor: css.color('rgba(255,128,0,0.5)') // RGB with alpha channel encoding
};
Once you have defined the color in one of the acceptable forms above, you can use it in your Twig templates:
<div style="color: {{ properties.primaryColor }}; background: {{ properties.secondaryColor.rgba }};">
<!-- ... -->
</div>
Since primaryColor
is a color object, you can access its attributes:
-
.rgba
gives you the specified color in thergba(red,green,blue,alpha)
format. -
.hex
gives you the specified color in the#rrggbb
or#rrggbbaa
format.
If you don't access an attribute, you will get the color in the hex format.
Within your stylesheets, you can use color properties in the following way:
$color: bsiProperty('primaryColor');
$backgroundColor: bsiProperty('secondaryColor');
h1 {
color: darken($color, 10%);
}
.header {
background-color: $backgroundColor;
}
To define a property as a URL, use the css.url
or css.dataUri
helpers:
const {css} = require('@bsi-cx/design-build');
module.exports = {
background: css.url(__dirname, 'content-elements', 'content', 'title', 'placeholder.png'),
foreground: css.dataUri(__dirname, 'content-elements', 'content', 'title', 'placeholder.png'),
};
Once you have defined the URL in one of the acceptable forms above, you can use it in your templates:
<div style="background-image: {{ properties.background.externalRefCss }}"></div>
<div style="background-image: {{ properties.foreground }}"></div>
Since background
and foreground
are objects, you can directly access their attributes:
-
.externalRef
gives you the path to the resource, e.g.../assets/placeholder-04f7dbccedf0c8a7dd7d.png
-
.inlineRef
gives you a data URI of the resource. -
.inlineRefCss
gives you the CSSurl()
representation with a data URI. -
.externalRefCss
gives you the CSSurl()
representation with a path to the resource. -
.css
gives you the CSSurl()
representation. If you usedcss.dataUri()
to construct the object, you will receive a data URI.
If you don't access an attribute, you will receive the value of .css
.
Within your stylesheets, you can use URL properties in the following way:
$background: bsiProperty('background');
.background {
background-image: $background;
}
To define a property as a numeric value with a unit, use the css.number
helper:
const {css} = require('@bsi-cx/design-build');
module.exports = {
margin: css.number('10px'),
padding: css.number('1rem'),
width: css.number('80%')
};
All standard CSS units are allowed. The use in templates and stylesheets is straightforward and similar to the other properties.
The HTML and Handlebars Templates this build produces, can be written in plain HTML or Twig. Using Twig has many advantages when it comes to code reuse and parameterizing your design. Coding Twig is simple and straightforward. This chapter gives you a quick overview on this package's custom Twig functions and how to use them.
To include an asset in your template, you can use the bsi_cx_asset(file, ?inline)
function:
<figure data-bsi-element="32f88ae6-f475-4fe5-90c0-b48f7355bd8d">
<img src="{{ bsi_cx_asset('./placeholder.png') }}" alt="Vestibulum pulvinar ex eget magna porttitor."/>
<figcaption data-bsi-element-part="3065924d-3847-43e4-9527-5c8f3485a60c">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</figcaption>
</div>
The function accepts two parameters:
-
path
is mandatory and specifies the path to the asset to include, relative to the current template. -
inline
is optional and can be set totrue
to inline the specified asset as data URI. The default isfalse
.
The function returns a string, which will be a URL or a data URI (if inline is set to true
) of the specified asset.
The build uses the mini-css-extract-plugin to extract all produced CSS to a single file.
You should include this CSS file in the root template of your design. To do so, you can use the bsi_cx_css_href()
or bsi_cx_css_inline()
function.
Use bsi_cx_css_href()
to place a URL to the CSS file:
<link rel="stylesheet" href="{{ bsi_cx_css_href() }}"/>
Use bsi_cx_css_inline()
to directly include the content of the CSS file inside your template:
<style>
{{ bsi_cx_css_inline() }}
</style>
The bsi_cx_css_inline()
function might be especially useful for email templates.
Ordinary JavaScript files can be included like normal assets by using the bsi_cx_asset
function.
In case of JavaScript modules, you need to use the following functions:
- Use
bsi_cx_js_module_href()
orbsi_cx_js_module_inline()
to include a single module. - Use
bsi_cx_js_module_missing_chunks_import()
orbsi_cx_js_module_missing_chunks_inline()
to include the related chunks. - Use
bsi_cx_js_module_runtime_href()
orbsi_cx_js_module_runtime_inline()
to include the related runtime chunk.
The *_href()
functions will return a URL, while the *_inline()
functions return the file's content. The following example
should illustrate the usage:
<!-- runtime -->
<script src="{{ bsi_cx_js_module_runtime_href() }}" defer="defer" data-bsi-remove-if="draft"></script>
<!-- modules -->
<script src="{{ bsi_cx_js_module_href('foo') }}" defer="defer" data-bsi-remove-if="draft"></script>
<script src="{{ bsi_cx_js_module_href('bar') }}" defer="defer" data-bsi-remove-if="draft"></script>
<!-- chunks -->
{{ bsi_cx_js_module_missing_chunks_import() }}
This will result in the following HTML:
<!-- runtime -->
<script src="./shared/runtime.js" defer="defer" data-bsi-remove-if="draft"></script>
<!-- modules -->
<script src="./modules/foo-e3b14801095c68975223.js" defer="defer" data-bsi-remove-if="draft"></script>
<script src="./modules/bar-0d874ea6e842d60b50c5.js" defer="defer" data-bsi-remove-if="draft"></script>
<!-- chunks -->
<script src="./vendors/85a0aa6070182a717e14.js" defer="defer" data-bsi-remove-if="draft"></script>
<script src="./vendors/76f6031a12ddc80a264b.js" defer="defer" data-bsi-remove-if="draft"></script>
<script src="./shared/59b150d5ab88386f4d73.js" defer="defer" data-bsi-remove-if="draft"></script>
As you can see, bsi_cx_js_module_missing_chunks_import()
directly creates the required script tags.
When using JavaScript modules, you should always include the runtime and missing chunks with the corresponding functions.
The BSI CX build has a builtin Lorem Ipsum sample text generator. Just use the bsi_cx_lorem(?words)
Twig function.
The function accepts one optional parameter, which defines the amount of words the output should contain.
Without any limitation, the function will output the whole internal buffer (about 750 characters).
<p>{{ bsi_cx_lorem(9) }}</p>
<p>Vivamus dapibus lobortis risus, nec fringilla lectus consectetur at.</p>
If you have to use Handlebars inside your Twig templates, keep the following things in mind:
- Use
.hbs.twig
as file extension. This will trigger the build to produce a.hbs
file. - Wrap your Handlebars code with
{% verbatim %}
and{% endverbatim %}
.
See the following example for details:
<div data-bsi-element="content-text" class="element content-text">
<p data-bsi-element-part="plain-text">
{% verbatim %}{{bsi.nls 'text_'}}{% endverbatim %}
</p>
</div>
Folder Structure
Configuration
Design Specification
Templates
Run the Build
Build Multiple Templates
Legacy Design Format
Hash ZIP Files
Disable Source Maps
Bundle JavaScript Modules
Change the Development Server Port
Add Webpack Rules and Plugins
Copy Additional Files
Copy a Configuration
Customize the Assets Filename
Add File Extensions for Static Assets
Specification
Design
Content Element Group
Content Element
Content Element Part
Dropzones
Extending Dropzones
Style Configuration
HTML Editor Configuration
Websites
Translations
Using Raw Values
Compatible Versions and Designs
Properties
Colors
URLs
Numeric Values
Templates
Include Assets
Include Stylesheets
Include JavaScript
Sample Text Provider
Twig and Handlebars