<div id="richtext-13709-88957-wrapper" class="richtext">
<input id="richtext-13709-88957" type="hidden" value="">
<trix-toolbar id="richtext-13709-88957-toolbar" class="richtext__toolbar">
<div class="richtext__toolbar-buttons">
<button class="richtext__toolbar-button" type="button" title="Fett" data-trix-attribute="bold" data-trix-key="b" tabindex="-1">
<svg class="icon icon--bold richtext__toolbar-button-icon" viewBox="0 0 200 200" aria-hidden="true">
<use xlink:href="/assets/icons/icons.3bafb6df0d.svg#bold"></use>
</svg> </button>
<button class="richtext__toolbar-button" type="button" title="Kursiv" data-trix-attribute="italic" data-trix-key="i" tabindex="-1">
<svg class="icon icon--italic richtext__toolbar-button-icon" viewBox="0 0 200 200" aria-hidden="true">
<use xlink:href="/assets/icons/icons.3bafb6df0d.svg#italic"></use>
</svg> </button>
<button class="richtext__toolbar-button" type="button" title="Durchgestrichen" data-trix-attribute="strikethrough" data-trix-key="s" tabindex="-1">
<svg class="icon icon--strikethrough richtext__toolbar-button-icon" viewBox="0 0 200 200" aria-hidden="true">
<use xlink:href="/assets/icons/icons.3bafb6df0d.svg#strikethrough"></use>
</svg> </button>
<button class="richtext__toolbar-button" type="button" title="Als Überschrift der Ebene 1 formattieren" data-trix-attribute="heading2" data-trix-key="h" tabindex="-1">
<svg class="icon icon--heading-1 richtext__toolbar-button-icon" viewBox="0 0 200 200" aria-hidden="true">
<use xlink:href="/assets/icons/icons.3bafb6df0d.svg#heading-1"></use>
</svg> </button>
<button class="richtext__toolbar-button" type="button" title="Als Überschrift der Ebene 2 formattieren" data-trix-attribute="heading3" data-trix-key="n" tabindex="-1">
<svg class="icon icon--heading-2 richtext__toolbar-button-icon" viewBox="0 0 200 200" aria-hidden="true">
<use xlink:href="/assets/icons/icons.3bafb6df0d.svg#heading-2"></use>
</svg> </button>
<button class="richtext__toolbar-button" type="button" title="Als Zitat formattieren" data-trix-attribute="quote" data-trix-key="q" tabindex="-1">
<svg class="icon icon--blockquote richtext__toolbar-button-icon" viewBox="0 0 200 200" aria-hidden="true">
<use xlink:href="/assets/icons/icons.3bafb6df0d.svg#blockquote"></use>
</svg> </button>
<button class="richtext__toolbar-button" type="button" title="Ungeordnete Liste" data-trix-attribute="bullet" data-trix-key="l" tabindex="-1">
<svg class="icon icon--unordered-list richtext__toolbar-button-icon" viewBox="0 0 200 200" aria-hidden="true">
<use xlink:href="/assets/icons/icons.3bafb6df0d.svg#unordered-list"></use>
</svg> </button>
<button class="richtext__toolbar-button" type="button" title="Nummerierte Liste" data-trix-attribute="number" data-trix-key="o" tabindex="-1">
<svg class="icon icon--ordered-list richtext__toolbar-button-icon" viewBox="0 0 200 200" aria-hidden="true">
<use xlink:href="/assets/icons/icons.3bafb6df0d.svg#ordered-list"></use>
</svg> </button>
<button class="richtext__toolbar-button" type="button" title="Als Quellcode formattieren" data-trix-attribute="code" data-trix-key="c" tabindex="-1">
<svg class="icon icon--code richtext__toolbar-button-icon" viewBox="0 0 200 200" aria-hidden="true">
<use xlink:href="/assets/icons/icons.3bafb6df0d.svg#code"></use>
</svg> </button>
<button class="richtext__toolbar-button" type="button" title="Link" data-trix-attribute="href" data-trix-action="link" data-trix-key="a" tabindex="-1">
<svg class="icon icon--link richtext__toolbar-button-icon" viewBox="0 0 200 200" aria-hidden="true">
<use xlink:href="/assets/icons/icons.3bafb6df0d.svg#link"></use>
</svg> </button>
</div>
<div class="richtext__toolbar-dialogs" data-trix-dialogs>
<div class="richtext__toolbar-dialog richtext__toolbar-dialog--link" data-trix-dialog="href" data-trix-dialog-attribute="href">
<input type="url" data-name="href" class="richtext__toolbar-dialog-input" placeholder="https://beispiel-url.de" aria-label="URL" data-trix-validate-href required data-trix-input>
<button class="richtext__toolbar-button" type="button" data-trix-method="setAttribute">
<svg class="icon icon--link richtext__toolbar-button-icon" viewBox="0 0 200 200" aria-hidden="true">
<use xlink:href="/assets/icons/icons.3bafb6df0d.svg#link"></use>
</svg>
<span class="richtext__toolbar-button-text">
Link speichern
</span>
</button>
<button class="richtext__toolbar-button" title="Link entfernen" type="button" data-trix-method="removeAttribute">
<svg class="icon icon--unlink richtext__toolbar-button-icon" viewBox="0 0 200 200" aria-hidden="true">
<use xlink:href="/assets/icons/icons.3bafb6df0d.svg#unlink"></use>
</svg> </button>
</div>
</div>
</trix-toolbar>
<trix-editor class="richtext__input" input="richtext-13709-88957" toolbar="richtext-13709-88957-toolbar"> </trix-editor>
</div>
{% set id = id ??? html_id('richtext') %}
{% set richtextActions = {
bold: {
title: 'Bold' | t('site'),
icon: 'bold',
htmlTags: ['b', 'strong'],
key: 'b',
},
italic: {
title: 'Italic' | t('site'),
icon: 'italic',
htmlTags: ['em', 'i'],
key: 'i',
},
strikethrough: {
title: 'Strikethrough' | t('site'),
icon: 'strikethrough',
htmlTags: ['s'],
key: 's',
},
heading2: {
title: 'Format as headline level 1' | t('site'),
icon: 'heading-1',
htmlTags: ['h2'],
key: 'h',
},
heading3: {
title: 'Format as headline level 2' | t('site'),
icon: 'heading-2',
htmlTags: ['h3'],
key: 'n',
},
quote: {
title: 'Format as quote' | t('site'),
icon: 'blockquote',
htmlTags: ['blockquote', 'cite'],
key: 'q',
},
ulist: {
title: 'Unordered list' | t('site'),
icon: 'unordered-list',
attribute: 'bullet',
htmlTags: ['ul', 'li'],
key: 'l',
},
olist: {
title: 'Ordered list' | t('site'),
icon: 'ordered-list',
attribute: 'number',
htmlTags: ['ol', 'li'],
key: 'o',
},
code: {
title: 'Format as code' | t('site'),
icon: 'code',
htmlTags: ['code'],
key: 'c',
},
link: {
title: 'Link' | t('site'),
icon: 'link',
action: 'link',
attribute: 'href',
htmlTags: ['a'],
key: 'a',
},
} %}
{% set buttons = buttons | default(richtextActions|keys) %}
<div {{ html_attributes({
id: 'wrapper' | namespaceInputId(id),
class: 'richtext',
}, attrs ?? {}) }}>
<input {{ html_attributes({
id,
type: 'hidden',
name: name ?? null,
value: value | default('') | raw,
}, inputAttrs ?? {}) }}>
<trix-toolbar id="{{ 'toolbar' | namespaceInputId(id) }}" class="richtext__toolbar">
<div class="richtext__toolbar-buttons">
{% for button in buttons %}
{% if button in richtextActions|keys %}
<button {{ html_attributes({
class: 'richtext__toolbar-button',
type: 'button',
title: richtextActions[button].title,
'data-trix-attribute': richtextActions[button].attribute ?? button,
'data-trix-action': richtextActions[button].action ?? null,
'data-trix-key': richtextActions[button].key ?? null,
tabindex: '-1',
}) }}>
{% include '@icon' with {
icon: richtextActions[button].icon,
class: 'richtext__toolbar-button-icon',
} only %}
</button>
{% endif %}
{% endfor %}
</div>
<div class="richtext__toolbar-dialogs" data-trix-dialogs>
<div class="richtext__toolbar-dialog richtext__toolbar-dialog--link" data-trix-dialog="href" data-trix-dialog-attribute="href">
<input type="url" data-name="href" class="richtext__toolbar-dialog-input" placeholder="{{ 'https://example.com' | t('site') }}" aria-label="{{ 'URL' | t('site') }}" data-trix-validate-href required data-trix-input>
<button class="richtext__toolbar-button" type="button" data-trix-method="setAttribute">
{% include '@icon' with {
icon: 'link',
class: 'richtext__toolbar-button-icon',
} only %}
<span class="richtext__toolbar-button-text">
{{ 'Save link' | t('site') }}
</span>
</button>
<button class="richtext__toolbar-button" title="{{ 'Remove link' | t('site') }}" type="button" data-trix-method="removeAttribute">
{% include '@icon' with {
icon: 'unlink',
class: 'richtext__toolbar-button-icon',
} only %}
</button>
</div>
</div>
</trix-toolbar>
<trix-editor {{ html_attributes({
class: 'richtext__input',
input: id | namespaceInputId,
toolbar: 'toolbar' | namespaceInputId(id) | namespaceInputId,
}, inputAttrs ?? {}) }}> </trix-editor>
</div>
/* No context defined. */
.richtext {
--focus-outline-offset: 0;
--focus-outline-width: 3px;
--focus-outline-color: var(--richtext-focus-outline-color, var(--form-focus-color));
background-color: var(--richtext-background-color, var(--color-white));
border-color: var(--richtext-border-color, var(--form-color));
border-style: solid;
border-width: 2px;
color: var(--richtext-color, var(--text-color));
&:has(:not(.richtext__toolbar-dialog-input, .richtext__toolbar-button):focus-visible) {
@include use-focus-outline();
}
}
.richtext__toolbar {
background-color: var(--richtext-toolbar-background-color, var(--color-midnight-50));
border-block-end: 1px solid var(--richtext-toolbar-border-color, var(--color-midnight-100));
}
.richtext__toolbar-buttons {
display: flex;
flex-wrap: wrap;
padding-inline: 1.2rem;
}
.richtext__toolbar-button {
align-items: center;
color: var(--richtext-toolbar-color, var(--color-midnight-900));
display: flex;
flex-shrink: 0;
font-size: 2rem;
gap: 0.8rem;
justify-content: center;
padding: 0.8rem;
transition-property: background-color;
&:is(:hover, :focus-visible, [data-trix-active]) {
background-color: var(--richtext-toolbar-background-color, var(--color-midnight-100));
}
}
.richtext__toolbar-button-text {
font-size: 1.6rem;
}
.richtext__toolbar-dialog .richtext__toolbar-button {
background-color: var(--color-midnight-100);
padding: 1.6rem;
&:is(:hover, :focus-visible, [data-trix-active]) {
background-color: var(--color-midnight-200);
}
&:not(:first-of-type) {
border-inline-start: 1px solid var(--color-midnight-300);
}
}
.richtext__toolbar-dialog {
border-block: 1px solid var(--richtext-toolbar-border-color, var(--color-midnight-300));
display: none;
margin-block-end: -1px;
&:is([data-trix-active]) {
display: flex !important;
}
}
.richtext__toolbar-dialog-input {
--focus-outline-offset: -3px;
flex-grow: 1;
padding-block: 1.6rem;
padding-inline: 2.4rem;
}
.richtext__input {
--focus-outline-color: transparent;
--focus-outline-width: 0;
font-size: 1.8rem;
line-height: 2.4rem;
max-block-size: calc(10lh + 2.4rem);
min-block-size: calc(3lh + 2.4rem);
overflow: auto;
padding-block: 1.2rem;
padding-inline: 2rem;
> * + * {
margin-block-start: 1.5rem;
}
:is(h2) {
font-size: 1.3em;
font-weight: bold;
}
:is(h3) {
font-size: 1.1em;
font-weight: bold;
}
:is(blockquote) {
border-inline-start: 0.5rem solid currentColor;
padding-inline-start: 1.5rem;
}
:is(ul, ol) {
padding-inline-start: 2rem;
}
:is(pre) {
font-family: monospace;
white-space: nowrap;
}
:is(hr) {
border-block-start: 1px solid currentColor;
}
:is(a) {
color: var(--hyperlink-color);
text-decoration-color: var(--hyperlink-color);
text-decoration-line: underline;
text-decoration-style: solid;
text-decoration-thickness: 1px;
}
}
import type Trix from 'trix';
import onLoad from '../../../javascripts/utils/onLoad';
onLoad('.richtext', async () => {
document.querySelectorAll<HTMLInputElement>('input[data-trix-validate-href]').forEach(($input) => {
$input.name = $input.dataset.name ?? '';
});
const { default: trix } = await import(/* webpackChunkName: "trix" */ 'trix') as { default: Trix };
trix.config.blockAttributes.heading2 = {
tagName: 'h2',
terminal: true,
breakOnReturn: true,
group: false,
};
trix.config.blockAttributes.heading3 = {
tagName: 'h3',
terminal: true,
breakOnReturn: true,
group: false,
};
trix.config.blockAttributes.default = {
tagName: 'p',
parse: false,
breakOnReturn: true,
};
trix.Block.prototype.breaksOnReturn = function breaksOnReturn() {
const attr = this.getLastAttribute();
const config = trix.config.blockAttributes[attr || "default"];
return config ? config.breakOnReturn : false;
};
trix.LineBreakInsertion.prototype.shouldInsertBlockBreak = function shouldInsertBlockBreak() {
if (this.block.hasAttributes() && this.block.isListItem() && !this.block.isEmpty()) {
return this.startLocation.offset > 0;
}
return !this.shouldBreakFormattedBlock() ? this.breaksOnReturn : false;
};
});
document.addEventListener('trix-attachment-add', (event) => {
event.preventDefault();
});
No notes defined.