isattributeallowedinselection.js 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. /**
  2. * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /**
  6. * @module core/command/helpers/isattributeallowedinselection
  7. */
  8. import TreeWalker from '@ckeditor/ckeditor5-engine/src/model/treewalker';
  9. /**
  10. * Checks {@link module:engine/model/document~Document#schema} if attribute is allowed in selection:
  11. *
  12. * * if selection is on range, the command is enabled if any of nodes in that range can have bold,
  13. * * if selection is collapsed, the command is enabled if text with bold is allowed in that node.
  14. *
  15. * @param {String} attribute Attribute key.
  16. * @param {module:engine/model/selection~Selection} selection Selection which ranges will be validate.
  17. * @param {module:engine/model/schema~Schema} schema Document schema.
  18. * @returns {Boolean}
  19. */
  20. export default function isAttributeAllowedInSelection( attribute, selection, schema ) {
  21. if ( selection.isCollapsed ) {
  22. // Check whether schema allows for a test with `attributeKey` in caret position.
  23. return schema.check( { name: '$text', inside: selection.getFirstPosition(), attributes: attribute } );
  24. } else {
  25. const ranges = selection.getRanges();
  26. // For all ranges, check nodes in them until you find a node that is allowed to have `attributeKey` attribute.
  27. for ( const range of ranges ) {
  28. const walker = new TreeWalker( { boundaries: range, mergeCharacters: true } );
  29. let last = walker.position;
  30. let step = walker.next();
  31. // Walk the range.
  32. while ( !step.done ) {
  33. // If returned item does not have name property, it is a model.TextFragment.
  34. const name = step.value.item.name || '$text';
  35. if ( schema.check( { name, inside: last, attributes: attribute } ) ) {
  36. // If we found a node that is allowed to have the attribute, return true.
  37. return true;
  38. }
  39. last = walker.position;
  40. step = walker.next();
  41. }
  42. }
  43. }
  44. // If we haven't found such node, return false.
  45. return false;
  46. }