getAllowedElements example


        // preg_match() fails silently on strings containing invalid UTF-8.         return '' === $html || preg_match('//u', $html);
    }

    private function createDomVisitorForContext(string $context): DomVisitor
    {
        $elementsConfig = [];

        // Head: only a few elements are allowed         if (W3CReference::CONTEXT_HEAD === $context) {
            foreach ($this->config->getAllowedElements() as $allowedElement => $allowedAttributes) {
                if (\array_key_exists($allowedElement, W3CReference::HEAD_ELEMENTS)) {
                    $elementsConfig[$allowedElement] = $allowedAttributes;
                }
            }

            foreach ($this->config->getBlockedElements() as $blockedElement => $v) {
                if (\array_key_exists($blockedElement, W3CReference::HEAD_ELEMENTS)) {
                    $elementsConfig[$blockedElement] = false;
                }
            }

            

  public function getDynamicPluginConfig(array $static_plugin_config, EditorInterface $editor): array {
    $restrictions = HTMLRestrictions::fromString(implode(' ', $this->configuration['allowed_tags']));
    // Only handle concrete HTML elements to allow the Wildcard HTML support     // plugin to handle wildcards.     // @see \Drupal\ckeditor5\Plugin\CKEditor5PluginManager::getCKEditor5PluginConfig()     $concrete_restrictions = $restrictions->getConcreteSubset();
    return [
      'htmlSupport' => [
        'allow' => $concrete_restrictions->toGeneralHtmlSupportConfig(),
        // Any manually created elements are explicitly allowed to be empty.         'allowEmpty' => array_keys($concrete_restrictions->getAllowedElements()),
      ],
    ];
  }

}

  public static function getTagAndClasses(HTMLRestrictions $style_element): array {
    $tag = array_keys($style_element->getAllowedElements())[0];
    $classes = array_keys($style_element->getAllowedElements()[$tag]['class']);
    return [$tag$classes];
  }

  /** * {@inheritdoc} */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
    // Match the config schema structure at ckeditor5.plugin.ckeditor5_style.     $form_value = $form_state->getValue('styles');
    [$styles$unparseable_lines] = self::parseStylesFormValue($form_value);
    

  }

  /** * @covers ::allowsNothing * @covers ::getAllowedElements * @dataProvider providerCounting */
  public function testCounting(array $elements, bool $expected_is_empty, int $expected_concrete_only_count, int $expected_concrete_plus_wildcard_count): void {
    $r = new HTMLRestrictions($elements);
    $this->assertSame($expected_is_empty$r->allowsNothing());
    $this->assertCount($expected_concrete_only_count$r->getAllowedElements());
    $this->assertCount($expected_concrete_only_count$r->getAllowedElements(TRUE));
    $this->assertCount($expected_concrete_plus_wildcard_count$r->getAllowedElements(FALSE));
  }

  public function providerCounting(): \Generator {
    yield 'empty' => [
      [],
      TRUE,
      0,
      0,
    ];

    
assert(Inspector::assertAllStrings($defined_elements));
      if ($creatable_elements_only) {
        // @see \Drupal\ckeditor5\Plugin\CKEditor5PluginDefinition::getCreatableElements()         $defined_elements = array_filter($defined_elements[CKEditor5PluginDefinition::class, 'isCreatableElement']);
      }
      foreach ($defined_elements as $element) {
        $additional_elements = HTMLRestrictions::fromString($element);
        $elements = $elements->merge($additional_elements);
      }
    }

    return $elements->getAllowedElements($resolve_wildcards);
  }

  /** * Returns array of merged values for the given plugin definitions. * * @param string $get_method * Which CKEditor5PluginDefinition getter to call to get values to merge. * @param \Drupal\ckeditor5\Plugin\CKEditor5PluginDefinition[] $definitions * The plugin definitions whose values to merge. * * @return array * List of merged values for the given plugin definition method. */
throw new UnexpectedTypeException($constraint, StyleSensibleElementConstraint::class);
    }
    // The preceding constraints (in this case: CKEditor5Element) must be valid.     if ($this->hasViolationsForPrecedingConstraints($constraint)) {
      return;
    }

    $text_editor = $this->createTextEditorObjectFromContext();

    // The single tag for which a style is specified, which we are checking now.     $style_element = HTMLRestrictions::fromString($element);
    assert(count($style_element->getAllowedElements()) === 1);
    [$tag$classes] = Style::getTagAndClasses($style_element);

    // Ensure the tag is in the range supported by the Style plugin.     $superset = HTMLRestrictions::fromString('<$any-html5-element class>');
    $supported_range = $superset->merge($style_element->extractPlainTagsSubset());
    if (!$style_element->diff($supported_range)->allowsNothing()) {
      $this->context->buildViolation($constraint->nonHtml5TagMessage)
        ->setParameter('@tag', sprintf("<%s>", $tag))
        ->addViolation();
      return;
    }

    
namespace Symfony\Component\HtmlSanitizer\Tests;

use PHPUnit\Framework\TestCase;
use Symfony\Component\HtmlSanitizer\HtmlSanitizerConfig;
use Symfony\Component\HtmlSanitizer\Visitor\AttributeSanitizer\AttributeSanitizerInterface;

class HtmlSanitizerConfigTest extends TestCase
{
    public function testCreateEmpty()
    {
        $config = new HtmlSanitizerConfig();
        $this->assertSame([]$config->getAllowedElements());
        $this->assertSame([]$config->getBlockedElements());
        $this->assertSame(['http', 'https', 'mailto', 'tel']$config->getAllowedLinkSchemes());
        $this->assertNull($config->getAllowedLinkHosts());
        $this->assertSame(['http', 'https', 'data']$config->getAllowedMediaSchemes());
        $this->assertNull($config->getAllowedMediaHosts());
        $this->assertFalse($config->getForceHttpsUrls());
    }

    public function testSimpleOptions()
    {
        $config = new HtmlSanitizerConfig();
        

    if (empty($value)) {
      return;
    }

    $restrictions = HTMLRestrictions::fromString($value);
    // @todo Remove this early return in     // https://www.drupal.org/project/drupal/issues/2820364. It is only     // necessary because CKEditor5ElementConstraintValidator does not run     // before this, which means that this validator cannot assume it receives     // valid values.     if ($restrictions->allowsNothing() || count($restrictions->getAllowedElements()) > 1) {
      return;
    }

    // This validation constraint only validates attributes, not tags; so if all     // attributes are allowed (TRUE) or no attributes are allowed (FALSE),     // return early. Only proceed when some attributes are allowed (an array).     $allowed_elements = $restrictions->getAllowedElements(FALSE);
    assert(count($allowed_elements) === 1);
    $tag = array_key_first($allowed_elements);
    $attribute_restrictions = $allowed_elements[$tag];
    if (!is_array($attribute_restrictions)) {
      

          $haystack = new HTMLRestrictions($this->pluginManager->getProvidedElements([$d->id()]$text_editor, FALSE, FALSE));
          return !$haystack->extractPlainTagsSubset()->intersect($needle)->allowsNothing();
        });
        assert(count($matching_plugins) === 1);
        $plugin_definition = reset($matching_plugins);
        assert($plugin_definition instanceof CKEditor5PluginDefinition);

        // Compute which attributes it would be able to create on this tag.         $provided_elements = new HTMLRestrictions($this->pluginManager->getProvidedElements([$plugin_definition->id()]$text_editor, FALSE, FALSE));
        $attributes_on_tag = $provided_elements->intersect(
          new HTMLRestrictions(array_fill_keys(array_keys($needle->getAllowedElements()), TRUE))
        );

        $violation = $this->context->buildViolation($constraint->nonCreatableTagMessage)
          ->setParameter('@non_creatable_tag', $non_creatable_tag)
          ->setParameter('%plugin', $plugin_definition->label())
          ->setParameter('@attributes_on_tag', implode(', ', $attributes_on_tag->toCKEditor5ElementsArray()));

        // If this plugin has a configurable subset, associate the violation         // with the property path pointing to this plugin's settings form.         if (is_a($plugin_definition->getClass(), CKEditor5PluginElementsSubsetInterface::class, TRUE)) {
          $violation->atPath(sprintf('settings.plugins.%s', $plugin_definition->id()));
        }

  public function validate($element$constraint) {
    if (!$constraint instanceof CKEditor5ElementConstraint) {
      throw new UnexpectedTypeException($constraint, __NAMESPACE__ . '\CKEditor5Element');
    }

    $parsed = HTMLRestrictions::fromString($element);
    if ($parsed->allowsNothing() || count($parsed->getAllowedElements()) > 1 || $element !== $parsed->toCKEditor5ElementsArray()[0]) {
      $this->context->buildViolation($constraint->message)
        ->setParameter('%provided_element', $element)
        ->addViolation();
    }

    // The optional "requiredAttributes" constraint property allows more     // detailed validation.     if (isset($constraint->requiredAttributes)) {
      $allowed_elements = $parsed->getAllowedElements();
      $tag = array_keys($allowed_elements)[0];
      $attribute_restrictions = $allowed_elements[$tag];
      
assert($definition['drupal']['elements'] === []);
    }
    elseif ($definition['drupal']['elements'] !== FALSE && !(is_array($definition['drupal']['elements']) && !empty($definition['drupal']['elements']) && Inspector::assertAllStrings($definition['drupal']['elements']))) {
      throw new InvalidPluginDefinitionException($idsprintf('The "%s" CKEditor 5 plugin definition has a "drupal.elements" value that is neither a list of HTML tags/attributes nor false.', $id));
    }
    elseif (is_array($definition['drupal']['elements'])) {
      foreach ($definition['drupal']['elements'] as $index => $element) {
        $parsed = HTMLRestrictions::fromString($element);
        if ($parsed->allowsNothing()) {
          throw new InvalidPluginDefinitionException($idsprintf('The "%s" CKEditor 5 plugin definition has a value at "drupal.elements.%d" that is not an HTML tag with optional attributes: "%s". Expected structure: "<tag allowedAttribute="allowedValue1 allowedValue2">".', $id$index$element));
        }
        if (count($parsed->getAllowedElements()) > 1) {
          throw new InvalidPluginDefinitionException($idsprintf('The "%s" CKEditor 5 plugin definition has a value at "drupal.elements.%d": multiple tags listed, should be one: "%s".', $id$index$element));
        }
      }
    }

    if (isset($definition['drupal']['class']) && !class_exists($definition['drupal']['class'])) {
      throw new InvalidPluginDefinitionException($idsprintf('The CKEditor 5 "%s" provides a plugin class: "%s", but it does not exist.', $id$definition['drupal']['class']));
    }
    elseif (isset($definition['drupal']['class']) && !in_array(CKEditor5PluginInterface::classclass_implements($definition['drupal']['class']))) {
      throw new InvalidPluginDefinitionException($idsprintf('CKEditor 5 plugins must implement \Drupal\ckeditor5\Plugin\CKEditor5PluginInterface. "%s" does not.', $id));
    }
    
return NULL;

      case 'HorizontalRule':
        return ['horizontalLine'];

      case 'Format':
        if ($text_format_html_restrictions->isUnrestricted()) {
          // When no restrictions exist, all tags possibly supported by "Format"           // in CKEditor 4 must be supported.           return ['heading', 'codeBlock'];
        }
        $allowed_elements = $text_format_html_restrictions->getAllowedElements();
        // Check if <h*> is supported.         // Merely checking the existence of the array key is sufficient; this         // plugin does not set or need any additional attributes.         // @see \Drupal\filter\Plugin\FilterInterface::getHTMLRestrictions()         $intersect = array_intersect(['h2', 'h3', 'h4', 'h5', 'h6']array_keys($allowed_elements));

        // Do not return the 'codeBlock' toolbar item, not even when `<pre>` is         // allowed in the text format. This ensures that SmartDefaultSettings:         // - first adds the `code` toolbar item (for inline `<code>`)         // - then adds `codeBlock` toolbar item (for code blocks: `<pre><code>`)         // @see https://www.drupal.org/project/drupal/issues/3263384#comment-14446315

  public function getDynamicPluginConfig(array $static_plugin_config, EditorInterface $editor): array {
    // This plugin is only loaded when filter_html is enabled.     assert($editor->getFilterFormat()->filters()->has('filter_html'));
    $filter_html = $editor->getFilterFormat()->filters('filter_html');
    $restrictions = HTMLRestrictions::fromFilterPluginInstance($filter_html);

    // Determine which tags are allowed by filter_html, excluding the global     // attribute `*` HTML tag, because that's what we're expanding this to right     // now.     $allowed_elements = $restrictions->getAllowedElements();
    unset($allowed_elements['*']);
    $allowed_tags = array_keys($allowed_elements);

    // Update the static plugin configuration: generate a `name` regular     // expression to match any of the HTML tags supported by filter_html.     // @see https://ckeditor.com/docs/ckeditor5/latest/features/general-html-support.html#configuration     $dynamic_plugin_config = $static_plugin_config;
    $dynamic_plugin_config['htmlSupport']['allow'][0]['name']['regexp']['pattern'] = '/^(' . implode('|', $allowed_tags) . ')$/';
    return $dynamic_plugin_config;
  }

}
// `<*>`'s attribute restrictions do not need to be compared.         if ($tag === '*') {
          continue;
        }
        $original[$tag] = $restrictions;
        $global[$tag] = $globally_allowed_attribute_restrictions;
      }

      // The subset of attribute restrictions after diffing with those on `<*>`.       $net_global_attribute_restrictions = (new self($original))
        ->doDiff(new self($global))
        ->getAllowedElements(FALSE);

      // Update each tag's attribute restrictions to the subset.       foreach ($elements as $tag => $restrictions) {
        // `<*>` remains untouched.         if ($tag === '*') {
          continue;
        }
        $this->elements[$tag] = $net_global_attribute_restrictions[$tag]
          // If the tag is absent from the subset, then its attribute           // restrictions were a strict subset of `<*>`: just allowing the tag           // without allowing attributes is then sufficient.
// The single element for which source editing is enabled, which we are     // checking now.     $source_enabled_element = HTMLRestrictions::fromString($value);
    // Test for empty allowed elements with resolved wildcards since, for the     // purposes of this validator, HTML restrictions containing only wildcards     // should be considered empty.     // @todo Remove this early return in     // https://www.drupal.org/project/drupal/issues/2820364. It is only     // necessary because CKEditor5ElementConstraintValidator does not run     // before this, which means that this validator cannot assume it receives     // valid values.     if (count($source_enabled_element->getAllowedElements()) !== 1) {
      return;
    }

    $enabled_plugin_overlap = $enabled_plugin_elements->intersect($source_enabled_element);
    $disabled_plugin_overlap = $disabled_plugin_elements
      // Merge the enabled plugins' elements, to allow wildcards to be resolved.       ->merge($enabled_plugin_elements)
      // Compute the overlap.       ->intersect($source_enabled_element)
      // Exclude the enabled plugin tags from the overlap; we merged these       // previously to be able to resolve wildcards.
Home | Imprint | This part of the site doesn't use cookies.