medium-editor-rails 2.3.2 → 2.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 517e7d49f074c079067439b81a4a18c6f823fd0e
4
- data.tar.gz: 267ee3cda3176cb44557ec1ba3b925b26eaf86ec
3
+ metadata.gz: 9fbc5be5c8889b94516fe3d384de117a143a8f64
4
+ data.tar.gz: baa9b17e491b54932b130529bdc9c93a15bbd211
5
5
  SHA512:
6
- metadata.gz: f3b2005cc03fba7ddf20dbc2ddf726bfaa6e87f1609d5a286bd8d035cf170d24ac28882eca9557c3d70a6538018ea1a2b18eb15d50f597bda2f3cefd841c19de
7
- data.tar.gz: d0bbbd59734f772531e0464a810b9633bb621ade8dd0d973bbaf50e1a31a0a7e0305f6923141f7363a2e4f41165db64a84052ffc54eba90d9c382d36dc9ead99
6
+ metadata.gz: 5731769e8b3c8bcf932c2bf7f5a06c9a1e9c6e1fec3ae28e301e19c701623f7661ea3353cf6212c49cc3270a5ffa0dbc17ec7303af013ea0b32cf62a0f1e67ac
7
+ data.tar.gz: 4c75128963d9cb4cbcfadf3de3023576e5759f8b03e14e979fd58c5b01aecb3069722f75316125206e5ae4fdcf2945d4aacf185d4d2a38f0507a1fb1cbf9528a
data/README.md CHANGED
@@ -8,7 +8,7 @@ This gem integrates [Medium Editor](https://github.com/yabwe/medium-editor) with
8
8
 
9
9
  ## Version
10
10
 
11
- The latest version of Medium Editor bundled by this gem is [5.22.1](https://github.com/yabwe/medium-editor/releases)
11
+ The latest version of Medium Editor bundled by this gem is [5.23.2](https://github.com/yabwe/medium-editor/releases)
12
12
 
13
13
  ## Installation
14
14
 
data/Rakefile CHANGED
@@ -5,6 +5,7 @@ README_VERSION_REGEXP = /bundled by this gem is \[([^\]]*)\]/
5
5
  VERSION_FILE_REGEXP = /MEDIUM_EDITOR_VERSION\s.*/
6
6
 
7
7
  namespace :bower do
8
+ desc "updates JS version references in README and VERSION files"
8
9
  task :bump do
9
10
  bump_readme_file
10
11
  bump_version_file
@@ -1,6 +1,6 @@
1
1
  module MediumEditorRails
2
2
  module Rails
3
- VERSION = '2.3.2'
4
- MEDIUM_EDITOR_VERSION = '5.22.1'
3
+ VERSION = '2.3.3'
4
+ MEDIUM_EDITOR_VERSION = '5.23.2'
5
5
  end
6
6
  end
@@ -544,6 +544,9 @@ MediumEditor.extensions = {};
544
544
  Util.moveTextRangeIntoElement(textNodes[0], textNodes[textNodes.length - 1], anchor);
545
545
  anchor.setAttribute('href', href);
546
546
  if (target) {
547
+ if (target === '_blank') {
548
+ anchor.setAttribute('rel', 'noopener noreferrer');
549
+ }
547
550
  anchor.setAttribute('target', target);
548
551
  }
549
552
  return anchor;
@@ -629,11 +632,10 @@ MediumEditor.extensions = {};
629
632
  splitEndNodeIfNeeded: function (currentNode, newNode, matchEndIndex, currentTextIndex) {
630
633
  var textIndexOfEndOfFarthestNode,
631
634
  endSplitPoint;
632
- textIndexOfEndOfFarthestNode = currentTextIndex + (newNode || currentNode).nodeValue.length +
633
- (newNode ? currentNode.nodeValue.length : 0) -
634
- 1;
635
- endSplitPoint = (newNode || currentNode).nodeValue.length -
636
- (textIndexOfEndOfFarthestNode + 1 - matchEndIndex);
635
+ textIndexOfEndOfFarthestNode = currentTextIndex + currentNode.nodeValue.length +
636
+ (newNode ? newNode.nodeValue.length : 0) - 1;
637
+ endSplitPoint = matchEndIndex - currentTextIndex -
638
+ (newNode ? currentNode.nodeValue.length : 0);
637
639
  if (textIndexOfEndOfFarthestNode >= matchEndIndex &&
638
640
  currentTextIndex !== textIndexOfEndOfFarthestNode &&
639
641
  endSplitPoint !== 0) {
@@ -990,12 +992,14 @@ MediumEditor.extensions = {};
990
992
  var i, url = anchorUrl || false;
991
993
  if (el.nodeName.toLowerCase() === 'a') {
992
994
  el.target = '_blank';
995
+ el.rel = 'noopener noreferrer';
993
996
  } else {
994
997
  el = el.getElementsByTagName('a');
995
998
 
996
999
  for (i = 0; i < el.length; i += 1) {
997
1000
  if (false === url || url === el[i].attributes.href.value) {
998
1001
  el[i].target = '_blank';
1002
+ el[i].rel = 'noopener noreferrer';
999
1003
  }
1000
1004
  }
1001
1005
  }
@@ -1009,17 +1013,24 @@ MediumEditor.extensions = {};
1009
1013
  var i;
1010
1014
  if (el.nodeName.toLowerCase() === 'a') {
1011
1015
  el.removeAttribute('target');
1016
+ el.removeAttribute('rel');
1012
1017
  } else {
1013
1018
  el = el.getElementsByTagName('a');
1014
1019
 
1015
1020
  for (i = 0; i < el.length; i += 1) {
1016
1021
  if (anchorUrl === el[i].attributes.href.value) {
1017
1022
  el[i].removeAttribute('target');
1023
+ el[i].removeAttribute('rel');
1018
1024
  }
1019
1025
  }
1020
1026
  }
1021
1027
  },
1022
1028
 
1029
+ /*
1030
+ * this function adds one or several classes on an a element.
1031
+ * if el parameter is not an a, it will look for a children of el.
1032
+ * if no a children are found, it will look for the a parent.
1033
+ */
1023
1034
  addClassToAnchors: function (el, buttonClass) {
1024
1035
  var classes = buttonClass.split(' '),
1025
1036
  i,
@@ -1029,7 +1040,13 @@ MediumEditor.extensions = {};
1029
1040
  el.classList.add(classes[j]);
1030
1041
  }
1031
1042
  } else {
1032
- el = el.getElementsByTagName('a');
1043
+ var aChildren = el.getElementsByTagName('a');
1044
+ if (aChildren.length === 0) {
1045
+ var parentAnchor = Util.getClosestTag(el, 'a');
1046
+ el = parentAnchor ? [parentAnchor] : [];
1047
+ } else {
1048
+ el = aChildren;
1049
+ }
1033
1050
  for (i = 0; i < el.length; i += 1) {
1034
1051
  for (j = 0; j < classes.length; j += 1) {
1035
1052
  el[i].classList.add(classes[j]);
@@ -2485,15 +2502,17 @@ MediumEditor.extensions = {};
2485
2502
  win = this.base.options.contentWindow,
2486
2503
  doc = this.base.options.ownerDocument;
2487
2504
 
2488
- targets = MediumEditor.util.isElement(targets) || [win, doc].indexOf(targets) > -1 ? [targets] : targets;
2505
+ if (targets !== null) {
2506
+ targets = MediumEditor.util.isElement(targets) || [win, doc].indexOf(targets) > -1 ? [targets] : targets;
2489
2507
 
2490
- Array.prototype.forEach.call(targets, function (target) {
2491
- index = this.indexOfListener(target, event, listener, useCapture);
2492
- if (index !== -1) {
2493
- e = this.events.splice(index, 1)[0];
2494
- e[0].removeEventListener(e[1], e[2], e[3]);
2495
- }
2496
- }.bind(this));
2508
+ Array.prototype.forEach.call(targets, function (target) {
2509
+ index = this.indexOfListener(target, event, listener, useCapture);
2510
+ if (index !== -1) {
2511
+ e = this.events.splice(index, 1)[0];
2512
+ e[0].removeEventListener(e[1], e[2], e[3]);
2513
+ }
2514
+ }.bind(this));
2515
+ }
2497
2516
  },
2498
2517
 
2499
2518
  indexOfListener: function (target, event, listener, useCapture) {
@@ -3350,6 +3369,14 @@ MediumEditor.extensions = {};
3350
3369
  contentDefault: '<b>image</b>',
3351
3370
  contentFA: '<i class="fa fa-picture-o"></i>'
3352
3371
  },
3372
+ 'html': {
3373
+ name: 'html',
3374
+ action: 'html',
3375
+ aria: 'evaluate html',
3376
+ tagNames: ['iframe', 'object'],
3377
+ contentDefault: '<b>html</b>',
3378
+ contentFA: '<i class="fa fa-code"></i>'
3379
+ },
3353
3380
  'orderedlist': {
3354
3381
  name: 'orderedlist',
3355
3382
  action: 'insertorderedlist',
@@ -3511,6 +3538,7 @@ MediumEditor.extensions = {};
3511
3538
  };
3512
3539
 
3513
3540
  })();
3541
+
3514
3542
  (function () {
3515
3543
  'use strict';
3516
3544
 
@@ -3743,8 +3771,8 @@ MediumEditor.extensions = {};
3743
3771
  // figure out how to deprecate? also consider `fa-` icon default implcations.
3744
3772
  template.push(
3745
3773
  '<div class="medium-editor-toolbar-form-row">',
3746
- '<input type="checkbox" class="medium-editor-toolbar-anchor-target">',
3747
- '<label>',
3774
+ '<input type="checkbox" class="medium-editor-toolbar-anchor-target" id="medium-editor-toolbar-anchor-target-field-' + this.getEditorId() + '">',
3775
+ '<label for="medium-editor-toolbar-anchor-target-field-' + this.getEditorId() + '">',
3748
3776
  this.targetCheckboxText,
3749
3777
  '</label>',
3750
3778
  '</div>'
@@ -3890,22 +3918,35 @@ MediumEditor.extensions = {};
3890
3918
  // Matches common external protocols "mailto:" "tel:" "maps:"
3891
3919
  // Matches relative hash link, begins with "#"
3892
3920
  var urlSchemeRegex = /^([a-z]+:)?\/\/|^(mailto|tel|maps):|^\#/i,
3921
+ hasScheme = urlSchemeRegex.test(value),
3922
+ scheme = '',
3893
3923
  // telRegex is a regex for checking if the string is a telephone number
3894
3924
  telRegex = /^\+?\s?\(?(?:\d\s?\-?\)?){3,20}$/,
3895
- split = value.split('?'),
3896
- path = split[0],
3897
- query = split[1];
3925
+ urlParts = value.match(/^(.*?)(?:\?(.*?))?(?:#(.*))?$/),
3926
+ path = urlParts[1],
3927
+ query = urlParts[2],
3928
+ fragment = urlParts[3];
3898
3929
 
3899
3930
  if (telRegex.test(value)) {
3900
3931
  return 'tel:' + value;
3901
- } else {
3902
- // Check for URL scheme and default to http:// if none found
3903
- return (urlSchemeRegex.test(value) ? '' : 'http://') +
3904
- // Ensure path is encoded
3905
- this.ensureEncodedUri(path) +
3906
- // Ensure query is encoded
3907
- (query === undefined ? '' : '?' + this.ensureEncodedQuery(query));
3908
3932
  }
3933
+
3934
+ if (!hasScheme) {
3935
+ var host = path.split('/')[0];
3936
+ // if the host part of the path looks like a hostname
3937
+ if (host.match(/.+(\.|:).+/) || host === 'localhost') {
3938
+ scheme = 'http://';
3939
+ }
3940
+ }
3941
+
3942
+ return scheme +
3943
+ // Ensure path is encoded
3944
+ this.ensureEncodedUri(path) +
3945
+ // Ensure query is encoded
3946
+ (query === undefined ? '' : '?' + this.ensureEncodedQuery(query)) +
3947
+ // Include fragment unencoded as encodeUriComponent is too
3948
+ // heavy handed for the many characters allowed in a fragment
3949
+ (fragment === undefined ? '' : '#' + fragment);
3909
3950
  },
3910
3951
 
3911
3952
  doFormCancel: function () {
@@ -4067,7 +4108,9 @@ MediumEditor.extensions = {};
4067
4108
  },
4068
4109
 
4069
4110
  hidePreview: function () {
4070
- this.anchorPreview.classList.remove('medium-editor-anchor-preview-active');
4111
+ if (this.anchorPreview) {
4112
+ this.anchorPreview.classList.remove('medium-editor-anchor-preview-active');
4113
+ }
4071
4114
  this.activeAnchor = null;
4072
4115
  },
4073
4116
 
@@ -4305,7 +4348,8 @@ MediumEditor.extensions = {};
4305
4348
  var WHITESPACE_CHARS,
4306
4349
  KNOWN_TLDS_FRAGMENT,
4307
4350
  LINK_REGEXP_TEXT,
4308
- KNOWN_TLDS_REGEXP;
4351
+ KNOWN_TLDS_REGEXP,
4352
+ LINK_REGEXP;
4309
4353
 
4310
4354
  WHITESPACE_CHARS = [' ', '\t', '\n', '\r', '\u00A0', '\u2000', '\u2001', '\u2002', '\u2003',
4311
4355
  '\u2028', '\u2029'];
@@ -4327,6 +4371,8 @@ MediumEditor.extensions = {};
4327
4371
 
4328
4372
  KNOWN_TLDS_REGEXP = new RegExp('^(' + KNOWN_TLDS_FRAGMENT + ')$', 'i');
4329
4373
 
4374
+ LINK_REGEXP = new RegExp(LINK_REGEXP_TEXT, 'gi');
4375
+
4330
4376
  function nodeIsNotInsideAnchorTag(node) {
4331
4377
  return !MediumEditor.util.getClosestTag(node, 'a');
4332
4378
  }
@@ -4508,12 +4554,11 @@ MediumEditor.extensions = {};
4508
4554
  },
4509
4555
 
4510
4556
  findLinkableText: function (contenteditable) {
4511
- var linkRegExp = new RegExp(LINK_REGEXP_TEXT, 'gi'),
4512
- textContent = contenteditable.textContent,
4557
+ var textContent = contenteditable.textContent,
4513
4558
  match = null,
4514
4559
  matches = [];
4515
4560
 
4516
- while ((match = linkRegExp.exec(textContent)) !== null) {
4561
+ while ((match = LINK_REGEXP.exec(textContent)) !== null) {
4517
4562
  var matchOk = true,
4518
4563
  matchEnd = match.index + match[0].length;
4519
4564
  // If the regexp detected something as a link that has text immediately preceding/following it, bail out.
@@ -5392,8 +5437,10 @@ MediumEditor.extensions = {};
5392
5437
  // on empty line, rects is empty so we grab information from the first container of the range
5393
5438
  if (rects.length) {
5394
5439
  top += rects[0].top;
5395
- } else {
5440
+ } else if (range.startContainer.getBoundingClientRect !== undefined) {
5396
5441
  top += range.startContainer.getBoundingClientRect().top;
5442
+ } else {
5443
+ top += range.getBoundingClientRect().top;
5397
5444
  }
5398
5445
  }
5399
5446
 
@@ -7111,6 +7158,11 @@ MediumEditor.extensions = {};
7111
7158
  return this.options.ownerDocument.execCommand('insertImage', false, src);
7112
7159
  }
7113
7160
 
7161
+ if (action === 'html') {
7162
+ var html = this.options.contentWindow.getSelection().toString().trim();
7163
+ return MediumEditor.util.insertHTMLCommand(this.options.ownerDocument, html);
7164
+ }
7165
+
7114
7166
  /* Issue: https://github.com/yabwe/medium-editor/issues/595
7115
7167
  * If the action is to justify the text */
7116
7168
  if (justifyAction.exec(action)) {
@@ -7826,7 +7878,7 @@ MediumEditor.parseVersionString = function (release) {
7826
7878
 
7827
7879
  MediumEditor.version = MediumEditor.parseVersionString.call(this, ({
7828
7880
  // grunt-bump looks for this:
7829
- 'version': '5.22.1'
7881
+ 'version': '5.23.2'
7830
7882
  }).version);
7831
7883
 
7832
7884
  return MediumEditor;
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: medium-editor-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.2
4
+ version: 2.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ahmet Sezgin Duran
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-01-18 00:00:00.000000000 Z
12
+ date: 2017-10-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties
@@ -94,7 +94,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
94
94
  version: '0'
95
95
  requirements: []
96
96
  rubyforge_project:
97
- rubygems_version: 2.5.1
97
+ rubygems_version: 2.6.13
98
98
  signing_key:
99
99
  specification_version: 4
100
100
  summary: Metdium Editor integrated in Rails asset pipeline