8
0

mentioneditingmarker.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /**
  2. * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /**
  6. * @module mention/mentionediting
  7. */
  8. import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
  9. import Command from '@ckeditor/ckeditor5-core/src/command';
  10. export function createMentionMarkerId( someString ) {
  11. const randId = parseInt( Math.random() * 10000 );
  12. const normalizedString = someString.toLowerCase().replace( ' ', '-' );
  13. return `mention:${ normalizedString }:${ randId }`;
  14. }
  15. class MentionCommand extends Command {
  16. /**
  17. * @inheritDoc
  18. */
  19. refresh() {
  20. // @todo implement refresh
  21. this.isEnabled = true;
  22. }
  23. /**
  24. * Executes the command.
  25. *
  26. * @protected
  27. * @param {Object} [options] Options for the executed command.
  28. * @param {String} [options.marker='@'] The mention marker.
  29. * @param {String} options.mention.
  30. * @param {String} [options.range].
  31. * @fires execute
  32. */
  33. execute( options = {} ) {
  34. const model = this.editor.model;
  35. const document = model.document;
  36. const selection = document.selection;
  37. const item = options.mention;
  38. const range = options.range || selection.getFirstRange();
  39. const label = item.label || item;
  40. model.change( writer => {
  41. writer.remove( range );
  42. const text = writer.createText( '@' + label );
  43. writer.insert( text, selection.focus );
  44. // TODO dumb
  45. const name = createMentionMarkerId( label );
  46. writer.addMarker( name, {
  47. range: writer.createRange( selection.focus.getShiftedBy( -text.data.length ), selection.focus ),
  48. usingOperation: true,
  49. affectData: true
  50. } );
  51. } );
  52. }
  53. }
  54. /**
  55. * The mention editing feature.
  56. *
  57. * @extends module:core/plugin~Plugin
  58. */
  59. export default class MentionElementEditing extends Plugin {
  60. /**
  61. * @inheritDoc
  62. */
  63. static get pluginName() {
  64. return 'MentionElementEditing';
  65. }
  66. /**
  67. * @inheritDoc
  68. */
  69. init() {
  70. const editor = this.editor;
  71. // Allow comment on text nodes.
  72. editor.model.schema.extend( '$text', { allowAttributes: [ 'mention' ] } );
  73. // Allow comment on all objects.
  74. editor.model.schema.addAttributeCheck( ( context, attributeName ) => {
  75. if ( attributeName == 'mention' && editor.model.schema.isObject( context.last ) ) {
  76. return true;
  77. }
  78. } );
  79. // Convert marker m->v for editing pipeline.
  80. editor.conversion.for( 'downcast' ).markerToHighlight( {
  81. model: 'mention',
  82. view: data => {
  83. const { id } = splitMarkerName( data.markerName );
  84. return {
  85. classes: [ 'mention' ],
  86. attributes: {
  87. 'data-mention': id
  88. }
  89. };
  90. }
  91. } );
  92. // Convert marker v->m.
  93. editor.conversion.for( 'upcast' ).elementToMarker( {
  94. view: {
  95. name: 'mention',
  96. attribute: {
  97. id: /^\w/
  98. }
  99. },
  100. model: viewElement => 'mention:' + viewElement.getAttribute( 'id' )
  101. } );
  102. editor.commands.add( 'mention', new MentionCommand( editor ) );
  103. }
  104. }
  105. function splitMarkerName( name ) {
  106. const path = name.split( ':' );
  107. return { group: path[ 0 ], id: path[ 1 ] };
  108. }