diff --git a/config/schema/smart_trim.schema.yml b/config/schema/smart_trim.schema.yml index 10d42e7..7adacd9 100644 --- a/config/schema/smart_trim.schema.yml +++ b/config/schema/smart_trim.schema.yml @@ -55,3 +55,6 @@ field.formatter.settings.smart_trim: replace_tokens: type: boolean label: 'Replace tokens before trimming' + trim_options_allowed_html: + type: mapping + label: 'Allowed HTML tags' diff --git a/smart_trim.module b/smart_trim.module index b0257ea..a847e1e 100644 --- a/smart_trim.module +++ b/smart_trim.module @@ -5,6 +5,7 @@ * Nothing to see here. It's all about the Field/FieldFormatter. */ +use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Routing\RouteMatchInterface; /** @@ -20,6 +21,26 @@ function smart_trim_help($route_name, RouteMatchInterface $route_match): string return $output; } +/** + * Change tags from string to array to speed up the formatter view. + * + * @param array $element + * Form element. + * + * @param array $form_state + * Form state. + */ +function _smart_trim_validate_allowed_html($element, FormStateInterface $form_state) { + $tags = array(); + $value = isset($element['#value']) ? trim($element['#value']) : ''; + + if (!empty($value)) { + $tags = preg_split('/\s+|<|>/', $value, -1, PREG_SPLIT_NO_EMPTY); + } + + $form_state->setValue($element['#parents'], $tags); +} + /** * Implements hook_theme(). */ diff --git a/src/Plugin/Field/FieldFormatter/SmartTrimFormatter.php b/src/Plugin/Field/FieldFormatter/SmartTrimFormatter.php index d4bcdd5..ac28748 100644 --- a/src/Plugin/Field/FieldFormatter/SmartTrimFormatter.php +++ b/src/Plugin/Field/FieldFormatter/SmartTrimFormatter.php @@ -11,6 +11,7 @@ use Drupal\smart_trim\TruncateHTML; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Utility\Token; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Component\Utility\Xss; /** * Plugin implementation of the 'smart_trim' formatter. @@ -119,6 +120,7 @@ class SmartTrimFormatter extends FormatterBase implements ContainerFactoryPlugin ], 'summary_handler' => 'full', 'trim_options' => [], + 'trim_options_allowed_html' => [], ] + parent::defaultSettings(); } @@ -278,6 +280,32 @@ class SmartTrimFormatter extends FormatterBase implements ContainerFactoryPlugin '#states' => $more_states, ]; + $allowed_html = $this->getSetting('trim_options_allowed_html'); + + if (empty($allowed_html)) { + $tags = ''; + } + elseif (is_string($allowed_html)) { + $tags = $allowed_html; + } + else { + $tags = '<' . implode('> <', $allowed_html) . '>'; + } + + $element['trim_options_allowed_html'] = [ + '#title' => $this->t('Allowed HTML tags'), + '#type' => 'textfield', + '#size' => 20, + '#default_value' => $tags, + '#description' => $this->t('See Xss::filter() for more information', ['@link' => 'https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Component%21Utility%21Xss.php/function/Xss%3A%3Afilter']), + '#element_validate' => ['_smart_trim_validate_allowed_html'], + '#states' => [ + 'visible' => [ + ':input[name="fields[body][settings_edit_form][settings][trim_options][text]"]' => ['checked' => TRUE], + ], + ], + ]; + return $element; } @@ -407,7 +435,7 @@ class SmartTrimFormatter extends FormatterBase implements ContainerFactoryPlugin // Add space before each tag to ensure words don't run together. // Logic via https://stackoverflow.com/questions/12824899/strip-tags-replace-tags-by-space-rather-than-deleting-them $output = str_replace('<', ' <', $output); - $output = strip_tags($output); + $output = Xss::filter($output, $this->getSetting('trim_options_allowed_html')); $output = str_replace(' ', ' ', $output); $output = trim($output);