converters.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /**
  2. * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /**
  6. * @module image/image/converters
  7. */
  8. import ModelPosition from '@ckeditor/ckeditor5-engine/src/model/position';
  9. import first from '@ckeditor/ckeditor5-utils/src/first';
  10. /**
  11. * Returns a function that converts the image view representation:
  12. *
  13. * <figure class="image"><img src="..." alt="..."></img></figure>
  14. *
  15. * to the model representation:
  16. *
  17. * <image src="..." alt="..."></image>
  18. *
  19. * The entire content of the `<figure>` element except the first `<img>` is being converted as children
  20. * of the `<image>` model element.
  21. *
  22. * @returns {Function}
  23. */
  24. export function viewFigureToModel() {
  25. return dispatcher => {
  26. dispatcher.on( 'element:figure', converter );
  27. };
  28. function converter( evt, data, conversionApi ) {
  29. // Do not convert if this is not an "image figure".
  30. if ( !conversionApi.consumable.test( data.viewItem, { name: true, class: 'image' } ) ) {
  31. return;
  32. }
  33. // Find an image element inside the figure element.
  34. const viewImage = Array.from( data.viewItem.getChildren() ).find( viewChild => viewChild.is( 'img' ) );
  35. // Do not convert if image element is absent, is missing src attribute or was already converted.
  36. if ( !viewImage || !viewImage.hasAttribute( 'src' ) || !conversionApi.consumable.test( viewImage, { name: true } ) ) {
  37. return;
  38. }
  39. // Convert view image to model image.
  40. const conversionResult = conversionApi.convertItem( viewImage, data.modelCursor );
  41. // Get image element from conversion result.
  42. const modelImage = first( conversionResult.modelRange.getItems() );
  43. // When image wasn't successfully converted then finish conversion.
  44. if ( !modelImage ) {
  45. return;
  46. }
  47. // Convert rest of the figure element's children as an image children.
  48. conversionApi.convertChildren( data.viewItem, ModelPosition.createAt( modelImage ) );
  49. // Set image range as conversion result.
  50. data.modelRange = conversionResult.modelRange;
  51. // Continue conversion where image conversion ends.
  52. data.modelCursor = conversionResult.modelCursor;
  53. }
  54. }
  55. /**
  56. * Converter used to convert `srcset` model image's attribute to `srcset`, `sizes` and `width` attributes in the view.
  57. *
  58. * @return {Function}
  59. */
  60. export function srcsetAttributeConverter() {
  61. return dispatcher => {
  62. dispatcher.on( 'attribute:srcset:image', converter );
  63. };
  64. function converter( evt, data, consumable, conversionApi ) {
  65. if ( !consumable.consume( data.item, evt.name ) ) {
  66. return;
  67. }
  68. const figure = conversionApi.mapper.toViewElement( data.item );
  69. const img = figure.getChild( 0 );
  70. if ( data.attributeNewValue === null ) {
  71. const srcset = data.attributeOldValue;
  72. if ( srcset.data ) {
  73. img.removeAttribute( 'srcset' );
  74. img.removeAttribute( 'sizes' );
  75. if ( srcset.width ) {
  76. img.removeAttribute( 'width' );
  77. }
  78. }
  79. } else {
  80. const srcset = data.attributeNewValue;
  81. if ( srcset.data ) {
  82. img.setAttribute( 'srcset', srcset.data );
  83. // Always outputting `100vw`. See https://github.com/ckeditor/ckeditor5-image/issues/2.
  84. img.setAttribute( 'sizes', '100vw' );
  85. if ( srcset.width ) {
  86. img.setAttribute( 'width', srcset.width );
  87. }
  88. }
  89. }
  90. }
  91. }
  92. export function modelToViewAttributeConverter( attributeKey ) {
  93. return dispatcher => {
  94. dispatcher.on( `attribute:${ attributeKey }:image`, converter );
  95. };
  96. function converter( evt, data, consumable, conversionApi ) {
  97. if ( !consumable.consume( data.item, evt.name ) ) {
  98. return;
  99. }
  100. const figure = conversionApi.mapper.toViewElement( data.item );
  101. const img = figure.getChild( 0 );
  102. if ( data.attributeNewValue !== null ) {
  103. img.setAttribute( data.attributeKey, data.attributeNewValue );
  104. } else {
  105. img.removeAttribute( data.attributeKey );
  106. }
  107. }
  108. }