medium-editor
Advanced tools
Comparing version 5.7.0 to 5.8.0
@@ -0,1 +1,8 @@ | ||
5.8.0 / 2015-09-13 | ||
================== | ||
* Added relativeContainer options for the toolbar | ||
* Fix issue with auto-linking across consecutive list-items | ||
* Added beagle theme | ||
5.7.0 / 2015-08-21 | ||
@@ -2,0 +9,0 @@ ================== |
@@ -196,3 +196,4 @@ /*global module, require, process*/ | ||
'dist/css/themes/roman.css': 'src/sass/themes/roman.scss', | ||
'dist/css/themes/tim.css': 'src/sass/themes/tim.scss' | ||
'dist/css/themes/tim.css': 'src/sass/themes/tim.scss', | ||
'dist/css/themes/beagle.css': 'src/sass/themes/beagle.scss' | ||
} | ||
@@ -199,0 +200,0 @@ } |
{ | ||
"name": "medium-editor", | ||
"version": "5.7.0", | ||
"version": "5.8.0", | ||
"author": "Davi Ferreira <hi@daviferreira.com>", | ||
@@ -42,24 +42,24 @@ "contributors": [ | ||
"devDependencies": { | ||
"brfs": "1.4.0", | ||
"brfs": "1.4.1", | ||
"grunt": "0.4.5", | ||
"grunt-autoprefixer": "3.0.0", | ||
"grunt-bump": "0.3.1", | ||
"grunt-autoprefixer": "3.0.3", | ||
"grunt-bump": "0.5.0", | ||
"grunt-contrib-concat": "0.5.1", | ||
"grunt-contrib-connect": "0.10.1", | ||
"grunt-contrib-csslint": "0.4.0", | ||
"grunt-contrib-cssmin": "0.12.3", | ||
"grunt-contrib-jasmine": "0.8.2", | ||
"grunt-contrib-jshint": "0.11.2", | ||
"grunt-contrib-uglify": "0.9.1", | ||
"grunt-contrib-connect": "0.11.2", | ||
"grunt-contrib-csslint": "0.5.0", | ||
"grunt-contrib-cssmin": "0.13.0", | ||
"grunt-contrib-jasmine": "0.9.1", | ||
"grunt-contrib-jshint": "0.11.3", | ||
"grunt-contrib-uglify": "0.9.2", | ||
"grunt-contrib-watch": "0.6.1", | ||
"grunt-coveralls": "1.0.0", | ||
"grunt-jscs": "1.8.0", | ||
"grunt-jscs": "2.1.0", | ||
"grunt-plato": "1.3.0", | ||
"grunt-sass": "1.0.0", | ||
"grunt-saucelabs": "8.6.1", | ||
"grunt-template-jasmine-istanbul": "0.3.3", | ||
"jshint-stylish": "1.0.2", | ||
"load-grunt-tasks": "3.1.0", | ||
"lodash": "3.9.1", | ||
"time-grunt": "1.2.0" | ||
"grunt-template-jasmine-istanbul": "0.3.4", | ||
"jshint-stylish": "2.0.1", | ||
"load-grunt-tasks": "3.2.0", | ||
"lodash": "3.10.1", | ||
"time-grunt": "1.2.1" | ||
}, | ||
@@ -66,0 +66,0 @@ "scripts": { |
@@ -141,2 +141,3 @@ # MediumEditor | ||
static: false, | ||
relativeContainer: null | ||
@@ -160,4 +161,5 @@ /* options which only apply when static is true */ | ||
* __static__: enable/disable the toolbar always displaying in the same location relative to the medium-editor element. Default: `false` | ||
* __relativeContainer__: Toolbar is appended relative to a given DOM-Node instead of appending it to the body and position it absolute. | ||
##### Options which only apply when the `static` option is being used | ||
##### Options which only apply when the `static` option is being used: | ||
* __align__: `left`|`center`|`right` - When the __static__ option is `true`, this aligns the static toolbar relative to the medium-editor element. Default: `center` | ||
@@ -164,0 +166,0 @@ * __sticky__: When the __static__ option is `true`, this enables/disables the toolbar "sticking" to the viewport and staying visible on the screen while the page scrolls. Default: `false` |
@@ -442,2 +442,28 @@ /*global fireEvent, selectElementContentsAndFire */ | ||
}); | ||
// https://github.com/yabwe/medium-editor/issues/790 | ||
it('should not create a link when text in consecutive list items could be a valid url when combined', function () { | ||
this.el.innerHTML = '<ul><li>text ending in a period.</li><li>name - text starting with a TLD</li></ul>'; | ||
selectElementContentsAndFire(this.el); | ||
triggerAutolinking(this.el); | ||
var links = this.el.getElementsByTagName('a'); | ||
expect(links.length).toBe(0, 'A link was created without a valid url being in the text'); | ||
expect(this.el.innerHTML).toBe('<ul><li>text ending in a period.</li><li>name - text starting with a TLD</li></ul>', | ||
'Content does not contain a valid url, but auto-link caused the content to change'); | ||
}); | ||
// https://github.com/yabwe/medium-editor/issues/790 | ||
it('should not create a link which spans multiple list items', function () { | ||
this.el.innerHTML = '<ol><li>abc</li><li>www.example.com</li></ol>'; | ||
selectElementContentsAndFire(this.el); | ||
triggerAutolinking(this.el); | ||
var links = this.el.getElementsByTagName('a'), | ||
lastLi = this.el.querySelector('ol').lastChild; | ||
expect(links.length).toBe(1, 'There should have been exactly 1 link created'); | ||
expect(links[0].getAttribute('href')).toBe('http://www.example.com'); | ||
expect(lastLi.firstChild).toBe(links[0]); | ||
expect(lastLi.textContent).toBe('www.example.com'); | ||
}); | ||
}); | ||
@@ -444,0 +470,0 @@ }); |
@@ -533,2 +533,34 @@ /*global fireEvent, selectElementContents, | ||
}); | ||
describe('Relative Toolbars', function () { | ||
it('should contain relative toolbar class', function () { | ||
var relativeContainer = window.document.createElement('div'); | ||
relativeContainer.setAttribute('id', 'someRelativeDiv'); | ||
window.document.body.appendChild(relativeContainer); | ||
var editor = this.newMediumEditor('.editor', { | ||
toolbar: { | ||
relativeContainer: document.getElementById('someRelativeDiv') | ||
} | ||
}), | ||
toolbar = editor.getExtensionByName('toolbar'); | ||
expect(toolbar.getToolbarElement().classList.contains('medium-editor-relative-toolbar')).toBe(true); | ||
}); | ||
it('should be included in relative node', function () { | ||
var relativeContainer = window.document.createElement('div'); | ||
relativeContainer.setAttribute('id', 'someRelativeDiv'); | ||
window.document.body.appendChild(relativeContainer); | ||
var editor = this.newMediumEditor('.editor', { | ||
toolbar: { | ||
relativeContainer: document.getElementById('someRelativeDiv') | ||
} | ||
}), | ||
toolbarHTML = editor.getExtensionByName('toolbar').getToolbarElement().outerHTML; | ||
expect(document.getElementById('someRelativeDiv').innerHTML).toBe(toolbarHTML); | ||
}); | ||
}); | ||
}); |
@@ -1,27 +0,42 @@ | ||
var WHITESPACE_CHARS, | ||
KNOWN_TLDS_FRAGMENT, | ||
LINK_REGEXP_TEXT; | ||
(function () { | ||
'use strict'; | ||
WHITESPACE_CHARS = [' ', '\t', '\n', '\r', '\u00A0', '\u2000', '\u2001', '\u2002', '\u2003', | ||
var WHITESPACE_CHARS, | ||
KNOWN_TLDS_FRAGMENT, | ||
LINK_REGEXP_TEXT, | ||
IGNORED_BLOCK_ELEMENTS, | ||
KNOWN_TLDS_REGEXP, | ||
AUTO_LINK_BLOCK_ELEMENTS; | ||
WHITESPACE_CHARS = [' ', '\t', '\n', '\r', '\u00A0', '\u2000', '\u2001', '\u2002', '\u2003', | ||
'\u2028', '\u2029']; | ||
KNOWN_TLDS_FRAGMENT = 'com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|' + | ||
'xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|' + | ||
'bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|' + | ||
'fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|' + | ||
'is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|' + | ||
'mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|' + | ||
'pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|' + | ||
'tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw'; | ||
LINK_REGEXP_TEXT = | ||
'(' + | ||
// Version of Gruber URL Regexp optimized for JS: http://stackoverflow.com/a/17733640 | ||
'((?:(https?://|ftps?://|nntp://)|www\\d{0,3}[.]|[a-z0-9.\\-]+[.](' + KNOWN_TLDS_FRAGMENT + ')\\\/)\\S+(?:[^\\s`!\\[\\]{};:\'\".,?\u00AB\u00BB\u201C\u201D\u2018\u2019]))' + | ||
// Addition to above Regexp to support bare domains/one level subdomains with common non-i18n TLDs and without www prefix: | ||
')|(([a-z0-9\\-]+\\.)?[a-z0-9\\-]+\\.(' + KNOWN_TLDS_FRAGMENT + '))'; | ||
KNOWN_TLDS_FRAGMENT = 'com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|' + | ||
'xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|' + | ||
'bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|' + | ||
'fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|' + | ||
'is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|' + | ||
'mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|' + | ||
'pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|' + | ||
'tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw'; | ||
(function () { | ||
'use strict'; | ||
LINK_REGEXP_TEXT = | ||
'(' + | ||
// Version of Gruber URL Regexp optimized for JS: http://stackoverflow.com/a/17733640 | ||
'((?:(https?://|ftps?://|nntp://)|www\\d{0,3}[.]|[a-z0-9.\\-]+[.](' + KNOWN_TLDS_FRAGMENT + ')\\\/)\\S+(?:[^\\s`!\\[\\]{};:\'\".,?\u00AB\u00BB\u201C\u201D\u2018\u2019]))' + | ||
// Addition to above Regexp to support bare domains/one level subdomains with common non-i18n TLDs and without www prefix: | ||
')|(([a-z0-9\\-]+\\.)?[a-z0-9\\-]+\\.(' + KNOWN_TLDS_FRAGMENT + '))'; | ||
var KNOWN_TLDS_REGEXP = new RegExp('^(' + KNOWN_TLDS_FRAGMENT + ')$', 'i'); | ||
// Block elements to ignore when querying all block elements for whether they contain auto-linkable text | ||
// These are elements whose text content should be ignored, but instead the text of their child nodes | ||
// should be evaluated for auto-link text | ||
// (ie don't check the text of an <ol>, check the <li>'s inside of it instead) | ||
IGNORED_BLOCK_ELEMENTS = ['ol', 'ul', 'dl', 'table', 'tbody', 'tfoot', 'tr']; | ||
KNOWN_TLDS_REGEXP = new RegExp('^(' + KNOWN_TLDS_FRAGMENT + ')$', 'i'); | ||
// List of block elements to search for when trying to find auto-linkable text | ||
AUTO_LINK_BLOCK_ELEMENTS = MediumEditor.util.blockContainerElementNames.filter(function (name) { | ||
return (IGNORED_BLOCK_ELEMENTS.indexOf(name) === -1); | ||
}); | ||
function nodeIsNotInsideAnchorTag(node) { | ||
@@ -85,3 +100,3 @@ return !MediumEditor.util.getClosestTag(node, 'a'); | ||
// (Medium deletes the spaces/returns between P tags so the textContent ends up without paragraph spacing) | ||
var blockElements = contenteditable.querySelectorAll(MediumEditor.util.blockContainerElementNames.join(',')), | ||
var blockElements = contenteditable.querySelectorAll(AUTO_LINK_BLOCK_ELEMENTS.join(',')), | ||
documentModified = false; | ||
@@ -88,0 +103,0 @@ if (blockElements.length === 0) { |
@@ -72,2 +72,7 @@ (function () { | ||
/* relativeContainer: [node] | ||
* appending the toolbar to a given node instead of body | ||
*/ | ||
relativeContainer: null, | ||
init: function () { | ||
@@ -77,3 +82,8 @@ MediumEditor.Extension.prototype.init.apply(this, arguments); | ||
this.initThrottledMethods(); | ||
this.getEditorOption('elementsContainer').appendChild(this.getToolbarElement()); | ||
if (!this.relativeContainer) { | ||
this.getEditorOption('elementsContainer').appendChild(this.getToolbarElement()); | ||
} else { | ||
this.relativeContainer.appendChild(this.getToolbarElement()); | ||
} | ||
}, | ||
@@ -101,2 +111,4 @@ | ||
toolbar.className += ' static-toolbar'; | ||
} else if (this.relativeContainer) { | ||
toolbar.className += ' medium-editor-relative-toolbar'; | ||
} else { | ||
@@ -511,3 +523,3 @@ toolbar.className += ' medium-editor-stalker-toolbar'; | ||
if (this.static) { | ||
if (this.static && !this.relativeContainer) { | ||
this.showToolbar(); | ||
@@ -517,3 +529,7 @@ this.positionStaticToolbar(container); | ||
this.showToolbar(); | ||
this.positionToolbar(selection); | ||
// we don't need any absolute positioning if relativeContainer is set | ||
if (!this.relativeContainer) { | ||
this.positionToolbar(selection); | ||
} | ||
} | ||
@@ -520,0 +536,0 @@ |
@@ -25,2 +25,14 @@ /*global NodeFilter*/ | ||
// https://developer.mozilla.org/en-US/docs/Web/API/Node/contains | ||
// Some browsers (including phantom) don't return true for Node.contains(child) | ||
// if child is a text node. Detect these cases here and use a fallback | ||
// for calls to Util.isDescendant() | ||
var nodeContainsWorksWithTextNodes = false; | ||
try { | ||
var testParent = document.createElement('div'), | ||
testText = document.createTextNode(' '); | ||
testParent.appendChild(testText); | ||
nodeContainsWorksWithTextNodes = testParent.contains(testText); | ||
} catch (exc) {} | ||
var Util = { | ||
@@ -244,2 +256,5 @@ | ||
} | ||
if (nodeContainsWorksWithTextNodes || child.nodeType !== 3) { | ||
return parent.contains(child); | ||
} | ||
var node = child.parentNode; | ||
@@ -246,0 +261,0 @@ while (node !== null) { |
@@ -18,3 +18,3 @@ MediumEditor.parseVersionString = function (release) { | ||
// grunt-bump looks for this: | ||
'version': '5.7.0' | ||
'version': '5.8.0' | ||
}).version); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1565109
131
19067
635