medium-editor-tc-mention
Advanced tools
Comparing version 2.1.1 to 2.2.0
@@ -0,1 +1,7 @@ | ||
<a name="2.2.0"></a> | ||
# [2.2.0](https://github.com/tomchentw/medium-editor-tc-mention/compare/v2.1.1...v2.2.0) (2016-01-25) | ||
<a name="2.1.1"></a> | ||
@@ -2,0 +8,0 @@ ## [2.1.1](https://github.com/tomchentw/medium-editor-tc-mention/compare/v2.1.0...v2.1.1) (2015-11-25) |
"use strict"; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
var _expect = require("expect"); | ||
@@ -9,15 +7,11 @@ | ||
var _mochaJsdom = require("mocha-jsdom"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _mochaJsdom2 = _interopRequireDefault(_mochaJsdom); | ||
describe("index", function () { | ||
(0, _mochaJsdom2["default"])(); | ||
it("should be exported", function () { | ||
describe("index", function describeIndex() { | ||
it("should be exported", function it() { | ||
var Module = require("../index"); | ||
(0, _expect2["default"])(Module["default"]).toExist(); | ||
(0, _expect2["default"])(Module.TCMention).toExist(); | ||
(0, _expect2.default)(Module.default).toExist(); | ||
(0, _expect2.default)(Module.TCMention).toExist(); | ||
}); | ||
}); | ||
}); /* eslint-disable prefer-arrow-callback */ |
620
lib/index.js
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports.TCMention = exports.LEFT_ARROW_KEYCODE = undefined; | ||
exports.unwrapForTextNode = unwrapForTextNode; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
var _mediumEditor = require("medium-editor"); | ||
@@ -14,358 +13,339 @@ | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function last(text) { | ||
return text[text.length - 1]; | ||
return text[text.length - 1]; | ||
} | ||
var LEFT_ARROW_KEYCODE = 37; | ||
var LEFT_ARROW_KEYCODE = exports.LEFT_ARROW_KEYCODE = 37; | ||
exports.LEFT_ARROW_KEYCODE = LEFT_ARROW_KEYCODE; | ||
function unwrapForTextNode(el, doc) { | ||
var parentNode = el.parentNode, | ||
prevNode, | ||
currentNode; | ||
_mediumEditor2["default"].util.unwrap(el, doc); | ||
// Merge textNode | ||
currentNode = parentNode.lastChild; | ||
while (prevNode = currentNode.previousSibling) { | ||
if (3 === currentNode.nodeType && 3 === prevNode.nodeType) { | ||
prevNode.textContent += currentNode.textContent; | ||
parentNode.removeChild(currentNode); | ||
} | ||
currentNode = prevNode; | ||
var parentNode = el.parentNode; | ||
_mediumEditor2.default.util.unwrap(el, doc); | ||
// Merge textNode | ||
var currentNode = parentNode.lastChild; | ||
var prevNode = currentNode.previousSibling; | ||
while (prevNode) { | ||
if (currentNode.nodeType === 3 && prevNode.nodeType === 3) { | ||
prevNode.textContent += currentNode.textContent; | ||
parentNode.removeChild(currentNode); | ||
} | ||
currentNode = prevNode; | ||
prevNode = currentNode.previousSibling; | ||
} | ||
} | ||
var TCMention = _mediumEditor2["default"].Extension.extend({ | ||
name: "mention", | ||
var TCMention = exports.TCMention = _mediumEditor2.default.Extension.extend({ | ||
name: "mention", | ||
/* @deprecated: use extraPanelClassName. Will remove in next major (3.0.0) release | ||
* extraClassName: [string] | ||
* | ||
* Extra className to be added with the `medium-editor-mention-panel` element. | ||
*/ | ||
extraClassName: "", | ||
/* @deprecated: use extraPanelClassName. Will remove in next major (3.0.0) release | ||
* extraClassName: [string] | ||
* | ||
* Extra className to be added with the `medium-editor-mention-panel` element. | ||
*/ | ||
extraClassName: "", | ||
/* @deprecated: use extraActivePanelClassName. Will remove in next major (3.0.0) release | ||
* extraActiveClassName: [string] | ||
* | ||
* Extra active className to be added with the `medium-editor-mention-panel-active` element. | ||
*/ | ||
extraActiveClassName: "", | ||
/* @deprecated: use extraActivePanelClassName. Will remove in next major (3.0.0) release | ||
* extraActiveClassName: [string] | ||
* | ||
* Extra active className to be added with the `medium-editor-mention-panel-active` element. | ||
*/ | ||
extraActiveClassName: "", | ||
/* extraPanelClassName: [string] | ||
* | ||
* Extra className to be added with the `medium-editor-mention-panel` element. | ||
*/ | ||
extraPanelClassName: "", | ||
/* extraPanelClassName: [string] | ||
* | ||
* Extra className to be added with the `medium-editor-mention-panel` element. | ||
*/ | ||
extraPanelClassName: "", | ||
/* extraActivePanelClassName: [string] | ||
* | ||
* Extra active className to be added with the `medium-editor-mention-panel-active` element. | ||
*/ | ||
extraActivePanelClassName: "", | ||
/* extraActivePanelClassName: [string] | ||
* | ||
* Extra active className to be added with the `medium-editor-mention-panel-active` element. | ||
*/ | ||
extraActivePanelClassName: "", | ||
extraTriggerClassNameMap: {}, | ||
extraTriggerClassNameMap: {}, | ||
extraActiveTriggerClassNameMap: {}, | ||
extraActiveTriggerClassNameMap: {}, | ||
/* tagName: [string] | ||
* | ||
* Element tag name that would indicate that this mention. It will have | ||
* `medium-editor-mention-at` className applied on it. | ||
*/ | ||
tagName: "strong", | ||
/* tagName: [string] | ||
* | ||
* Element tag name that would indicate that this mention. It will have | ||
* `medium-editor-mention-at` className applied on it. | ||
*/ | ||
tagName: "strong", | ||
/* renderPanelContent: [function (panelEl: dom, currentMentionText: string, selectMentionCallback: function)] | ||
* | ||
* Render function that used to create the content of the panel when panel is show. | ||
* | ||
* @params panelEl: DOM element of the panel. | ||
* | ||
* @params currentMentionText: Often used as query criteria. e.g. @medium | ||
* | ||
* @params selectMentionCallback: | ||
* callback used in customized panel content. | ||
* | ||
* When called with null, it tells the Mention plugin to close the panel. | ||
* e.g. selectMentionCallback(null); | ||
* | ||
* When called with text, it tells the Mention plugin that the text is selected by the user. | ||
* e.g. selectMentionCallback("@mediumrocks") | ||
*/ | ||
renderPanelContent: function renderPanelContent() {}, | ||
/* renderPanelContent: [ | ||
* function (panelEl: dom, currentMentionText: string, selectMentionCallback: function) | ||
* ] | ||
* | ||
* Render function that used to create the content of the panel when panel is show. | ||
* | ||
* @params panelEl: DOM element of the panel. | ||
* | ||
* @params currentMentionText: Often used as query criteria. e.g. @medium | ||
* | ||
* @params selectMentionCallback: | ||
* callback used in customized panel content. | ||
* | ||
* When called with null, it tells the Mention plugin to close the panel. | ||
* e.g. selectMentionCallback(null); | ||
* | ||
* When called with text, it tells the Mention plugin that the text is selected by the user. | ||
* e.g. selectMentionCallback("@mediumrocks") | ||
*/ | ||
renderPanelContent: function renderPanelContent() {}, | ||
/* destroyPanelContent: [function (panelEl: dom)] | ||
* | ||
* Destroy function to remove any contents rendered by renderPanelContent before panelEl being removed from the document. | ||
* | ||
* @params panelEl: DOM element of the panel. | ||
*/ | ||
destroyPanelContent: function destroyPanelContent() {}, | ||
/* destroyPanelContent: [function (panelEl: dom)] | ||
* | ||
* Destroy function to remove any contents rendered by renderPanelContent | ||
* before panelEl being removed from the document. | ||
* | ||
* @params panelEl: DOM element of the panel. | ||
*/ | ||
destroyPanelContent: function destroyPanelContent() {}, | ||
activeTriggerList: ["@"], | ||
activeTriggerList: ["@"], | ||
triggerClassNameMap: { | ||
"#": "medium-editor-mention-hash", | ||
"@": "medium-editor-mention-at" | ||
}, | ||
triggerClassNameMap: { | ||
"#": "medium-editor-mention-hash", | ||
"@": "medium-editor-mention-at" | ||
}, | ||
activeTriggerClassNameMap: { | ||
"#": "medium-editor-mention-hash-active", | ||
"@": "medium-editor-mention-at-active" | ||
}, | ||
activeTriggerClassNameMap: { | ||
"#": "medium-editor-mention-hash-active", | ||
"@": "medium-editor-mention-at-active" | ||
}, | ||
hideOnBlurDelay: 300, | ||
hideOnBlurDelay: 300, | ||
init: function init() { | ||
this.initMentionPanel(); | ||
this.attachEventHandlers(); | ||
}, | ||
init: function init() { | ||
this.initMentionPanel(); | ||
this.attachEventHandlers(); | ||
}, | ||
destroy: function destroy() { | ||
if (this.mentionPanel) { | ||
if (this.mentionPanel.parentNode) { | ||
this.destroyPanelContent(this.mentionPanel); | ||
this.mentionPanel.parentNode.removeChild(this.mentionPanel); | ||
} | ||
delete this.mentionPanel; | ||
} | ||
}, | ||
initMentionPanel: function initMentionPanel() { | ||
var el = this.document.createElement("div"); | ||
destroy: function destroy() { | ||
if (this.mentionPanel) { | ||
if (this.mentionPanel.parentNode) { | ||
this.destroyPanelContent(this.mentionPanel); | ||
this.mentionPanel.parentNode.removeChild(this.mentionPanel); | ||
} | ||
delete this.mentionPanel; | ||
} | ||
}, | ||
el.classList.add("medium-editor-mention-panel"); | ||
if (this.extraPanelClassName || this.extraClassName) { | ||
el.classList.add(this.extraPanelClassName || this.extraClassName); | ||
} | ||
initMentionPanel: function initMentionPanel() { | ||
var el = this.document.createElement("div"); | ||
this.getEditorOption("elementsContainer").appendChild(el); | ||
el.classList.add("medium-editor-mention-panel"); | ||
if (this.extraPanelClassName || this.extraClassName) { | ||
el.classList.add(this.extraPanelClassName || this.extraClassName); | ||
} | ||
this.mentionPanel = el; | ||
}, | ||
attachEventHandlers: function attachEventHandlers() { | ||
if (this.hideOnBlurDelay !== null && this.hideOnBlurDelay !== undefined) { | ||
// for hideOnBlurDelay, the panel should hide after blur event | ||
this.subscribe("blur", this.handleBlur.bind(this)); | ||
// and clear out hide timeout if focus again | ||
this.subscribe("focus", this.handleFocus.bind(this)); | ||
} | ||
// if the editor changes its content, we have to show or hide the panel | ||
this.subscribe("editableKeyup", this.handleKeyup.bind(this)); | ||
}, | ||
handleBlur: function handleBlur() { | ||
var _this = this; | ||
this.getEditorOption("elementsContainer").appendChild(el); | ||
if (this.hideOnBlurDelay !== null && this.hideOnBlurDelay !== undefined) { | ||
this.hideOnBlurDelayId = setTimeout(function () { | ||
_this.hidePanel(false); | ||
}, this.hideOnBlurDelay); | ||
} | ||
}, | ||
handleFocus: function handleFocus() { | ||
if (this.hideOnBlurDelayId) { | ||
clearTimeout(this.hideOnBlurDelayId); | ||
this.hideOnBlurDelayId = null; | ||
} | ||
}, | ||
handleKeyup: function handleKeyup(event) { | ||
var keyCode = _mediumEditor2.default.util.getKeyCode(event); | ||
var isSpace = keyCode === _mediumEditor2.default.util.keyCode.SPACE; | ||
this.getWordFromSelection(event.target, isSpace ? -1 : 0); | ||
this.mentionPanel = el; | ||
}, | ||
if (!isSpace && this.activeTriggerList.indexOf(this.trigger) !== -1 && this.word.length > 1) { | ||
this.showPanel(); | ||
} else { | ||
this.hidePanel(keyCode === LEFT_ARROW_KEYCODE); | ||
} | ||
}, | ||
hidePanel: function hidePanel(isArrowTowardsLeft) { | ||
this.mentionPanel.classList.remove("medium-editor-mention-panel-active"); | ||
var extraActivePanelClassName = this.extraActivePanelClassName || this.extraActiveClassName; | ||
attachEventHandlers: function attachEventHandlers() { | ||
if (null != this.hideOnBlurDelay) { | ||
// for hideOnBlurDelay, the panel should hide after blur event | ||
this.subscribe("blur", this.handleBlur.bind(this)); | ||
// and clear out hide timeout if focus again | ||
this.subscribe("focus", this.handleFocus.bind(this)); | ||
} | ||
// if the editor changes its content, we have to show or hide the panel | ||
this.subscribe("editableKeyup", this.handleKeyup.bind(this)); | ||
}, | ||
if (extraActivePanelClassName) { | ||
this.mentionPanel.classList.remove(extraActivePanelClassName); | ||
} | ||
if (this.activeMentionAt) { | ||
this.activeMentionAt.classList.remove(this.activeTriggerClassName); | ||
if (this.extraActiveTriggerClassName) { | ||
this.activeMentionAt.classList.remove(this.extraActiveTriggerClassName); | ||
} | ||
} | ||
if (this.activeMentionAt) { | ||
// http://stackoverflow.com/a/27004526/1458162 | ||
var _activeMentionAt = this.activeMentionAt; | ||
var parentNode = _activeMentionAt.parentNode; | ||
var previousSibling = _activeMentionAt.previousSibling; | ||
var nextSibling = _activeMentionAt.nextSibling; | ||
var firstChild = _activeMentionAt.firstChild; | ||
handleBlur: function handleBlur() { | ||
var _this = this; | ||
var siblingNode = isArrowTowardsLeft ? previousSibling : nextSibling; | ||
var textNode = undefined; | ||
if (!siblingNode) { | ||
textNode = this.document.createTextNode(""); | ||
parentNode.appendChild(textNode); | ||
} else if (siblingNode.nodeType !== 3) { | ||
textNode = this.document.createTextNode(""); | ||
parentNode.insertBefore(textNode, siblingNode); | ||
} else { | ||
textNode = siblingNode; | ||
} | ||
var lastEmptyWord = last(firstChild.textContent); | ||
var hasLastEmptyWord = lastEmptyWord.trim().length === 0; | ||
if (hasLastEmptyWord) { | ||
var textContent = firstChild.textContent; | ||
if (null != this.hideOnBlurDelay) { | ||
this.hideOnBlurDelayId = setTimeout(function () { | ||
_this.hidePanel(false); | ||
}, this.hideOnBlurDelay); | ||
firstChild.textContent = textContent.substr(0, textContent.length - 1); | ||
textNode.textContent = "" + lastEmptyWord + textNode.textContent; | ||
} else { | ||
if (textNode.textContent.length === 0 && firstChild.textContent.length > 1) { | ||
textNode.textContent = " "; | ||
} | ||
}, | ||
} | ||
if (isArrowTowardsLeft) { | ||
_mediumEditor2.default.selection.select(this.document, textNode, textNode.length); | ||
} else { | ||
_mediumEditor2.default.selection.select(this.document, textNode, Math.min(textNode.length, 1)); | ||
} | ||
if (firstChild.textContent.length <= 1) { | ||
// LIKE core#execAction | ||
this.base.saveSelection(); | ||
unwrapForTextNode(this.activeMentionAt, this.document); | ||
this.base.restoreSelection(); | ||
} | ||
// | ||
this.activeMentionAt = null; | ||
} | ||
}, | ||
getWordFromSelection: function getWordFromSelection(target, initialDiff) { | ||
var _MediumEditor$selecti = _mediumEditor2.default.selection.getSelectionRange(this.document); | ||
handleFocus: function handleFocus() { | ||
if (this.hideOnBlurDelayId) { | ||
clearTimeout(this.hideOnBlurDelayId); | ||
this.hideOnBlurDelayId = null; | ||
} | ||
}, | ||
var startContainer = _MediumEditor$selecti.startContainer; | ||
var startOffset = _MediumEditor$selecti.startOffset; | ||
var endContainer = _MediumEditor$selecti.endContainer; | ||
handleKeyup: function handleKeyup(event) { | ||
var keyCode = _mediumEditor2["default"].util.getKeyCode(event); | ||
var isSpace = keyCode === _mediumEditor2["default"].util.keyCode.SPACE; | ||
this.getWordFromSelection(event.target, isSpace ? -1 : 0); | ||
if (startContainer !== endContainer) { | ||
return; | ||
} | ||
var textContent = startContainer.textContent; | ||
if (!isSpace && -1 !== this.activeTriggerList.indexOf(this.trigger) && 1 < this.word.length) { | ||
this.showPanel(); | ||
} else { | ||
this.hidePanel(keyCode === LEFT_ARROW_KEYCODE); | ||
} | ||
}, | ||
function getWordPosition(position, diff) { | ||
var prevText = textContent[position - 1]; | ||
if (prevText === null || prevText === undefined) { | ||
return position; | ||
} else if (prevText.trim().length === 0 || position <= 0 || textContent.length < position) { | ||
return position; | ||
} else { | ||
return getWordPosition(position + diff, diff); | ||
} | ||
} | ||
hidePanel: function hidePanel(isArrowTowardsLeft) { | ||
this.mentionPanel.classList.remove("medium-editor-mention-panel-active"); | ||
if (this.extraActivePanelClassName || this.extraActiveClassName) { | ||
this.mentionPanel.classList.remove(this.extraActivePanelClassName || this.extraActiveClassName); | ||
} | ||
if (this.activeMentionAt) { | ||
this.activeMentionAt.classList.remove(this.activeTriggerClassName); | ||
if (this.extraActiveTriggerClassName) { | ||
this.activeMentionAt.classList.remove(this.extraActiveTriggerClassName); | ||
} | ||
} | ||
if (this.activeMentionAt) { | ||
// http://stackoverflow.com/a/27004526/1458162 | ||
var _activeMentionAt = this.activeMentionAt; | ||
var parentNode = _activeMentionAt.parentNode; | ||
var previousSibling = _activeMentionAt.previousSibling; | ||
var nextSibling = _activeMentionAt.nextSibling; | ||
var firstChild = _activeMentionAt.firstChild; | ||
this.wordStart = getWordPosition(startOffset + initialDiff, -1); | ||
this.wordEnd = getWordPosition(startOffset + initialDiff, 1) - 1; | ||
this.word = textContent.slice(this.wordStart, this.wordEnd); | ||
this.trigger = this.word.slice(0, 1); | ||
this.triggerClassName = this.triggerClassNameMap[this.trigger]; | ||
this.activeTriggerClassName = this.activeTriggerClassNameMap[this.trigger]; | ||
// | ||
this.extraTriggerClassName = this.extraTriggerClassNameMap[this.trigger]; | ||
this.extraActiveTriggerClassName = this.extraActiveTriggerClassNameMap[this.trigger]; | ||
}, | ||
showPanel: function showPanel() { | ||
if (!this.mentionPanel.classList.contains("medium-editor-mention-panel-active")) { | ||
this.activatePanel(); | ||
this.wrapWordInMentionAt(); | ||
} | ||
this.positionPanel(); | ||
this.updatePanelContent(); | ||
}, | ||
activatePanel: function activatePanel() { | ||
this.mentionPanel.classList.add("medium-editor-mention-panel-active"); | ||
if (this.extraActivePanelClassName || this.extraActiveClassName) { | ||
this.mentionPanel.classList.add(this.extraActivePanelClassName || this.extraActiveClassName); | ||
} | ||
}, | ||
wrapWordInMentionAt: function wrapWordInMentionAt() { | ||
var selection = this.document.getSelection(); | ||
if (!selection.rangeCount) { | ||
return; | ||
} | ||
// http://stackoverflow.com/a/6328906/1458162 | ||
var range = selection.getRangeAt(0).cloneRange(); | ||
if (range.startContainer.parentNode.classList.contains(this.triggerClassName)) { | ||
this.activeMentionAt = range.startContainer.parentNode; | ||
} else { | ||
var nextWordEnd = Math.min(this.wordEnd, range.startContainer.textContent.length); | ||
range.setStart(range.startContainer, this.wordStart); | ||
range.setEnd(range.startContainer, nextWordEnd); | ||
// Instead, insert our own version of it. | ||
// TODO: Not sure why, but using <span> tag doens't work here | ||
var element = this.document.createElement(this.tagName); | ||
element.classList.add(this.triggerClassName); | ||
if (this.extraTriggerClassName) { | ||
element.classList.add(this.extraTriggerClassName); | ||
} | ||
this.activeMentionAt = element; | ||
// | ||
range.surroundContents(element); | ||
selection.removeAllRanges(); | ||
selection.addRange(range); | ||
// | ||
_mediumEditor2.default.selection.select(this.document, this.activeMentionAt.firstChild, this.word.length); | ||
} | ||
this.activeMentionAt.classList.add(this.activeTriggerClassName); | ||
if (this.extraActiveTriggerClassName) { | ||
this.activeMentionAt.classList.add(this.extraActiveTriggerClassName); | ||
} | ||
}, | ||
positionPanel: function positionPanel() { | ||
var _activeMentionAt$getB = this.activeMentionAt.getBoundingClientRect(); | ||
var siblingNode = isArrowTowardsLeft ? previousSibling : nextSibling; | ||
var textNode = undefined; | ||
if (!siblingNode) { | ||
textNode = this.document.createTextNode(""); | ||
parentNode.appendChild(textNode); | ||
} else if (3 !== siblingNode.nodeType) { | ||
textNode = this.document.createTextNode(""); | ||
parentNode.insertBefore(textNode, siblingNode); | ||
} else { | ||
textNode = siblingNode; | ||
} | ||
var lastEmptyWord = last(firstChild.textContent); | ||
var hasLastEmptyWord = 0 === lastEmptyWord.trim().length; | ||
if (hasLastEmptyWord) { | ||
firstChild.textContent = firstChild.textContent.substr(0, firstChild.textContent.length - 1); | ||
textNode.textContent = "" + lastEmptyWord + textNode.textContent; | ||
} else { | ||
if (0 === textNode.textContent.length && 1 < firstChild.textContent.length) { | ||
textNode.textContent = " "; | ||
} | ||
} | ||
if (isArrowTowardsLeft) { | ||
_mediumEditor2["default"].selection.select(this.document, textNode, textNode.length); | ||
} else { | ||
_mediumEditor2["default"].selection.select(this.document, textNode, Math.min(textNode.length, 1)); | ||
} | ||
if (1 >= firstChild.textContent.length) { | ||
// LIKE core#execAction | ||
this.base.saveSelection(); | ||
unwrapForTextNode(this.activeMentionAt, this.document); | ||
this.base.restoreSelection(); | ||
} | ||
// | ||
this.activeMentionAt = null; | ||
} | ||
}, | ||
var bottom = _activeMentionAt$getB.bottom; | ||
var left = _activeMentionAt$getB.left; | ||
var width = _activeMentionAt$getB.width; | ||
var _window = this.window; | ||
var pageXOffset = _window.pageXOffset; | ||
var pageYOffset = _window.pageYOffset; | ||
getWordFromSelection: function getWordFromSelection(target, initialDiff) { | ||
var _MediumEditor$selection$getSelectionRange = _mediumEditor2["default"].selection.getSelectionRange(this.document); | ||
var startContainer = _MediumEditor$selection$getSelectionRange.startContainer; | ||
var startOffset = _MediumEditor$selection$getSelectionRange.startOffset; | ||
var endContainer = _MediumEditor$selection$getSelectionRange.endContainer; | ||
var endOffset = _MediumEditor$selection$getSelectionRange.endOffset; | ||
if (startContainer !== endContainer) { | ||
return; | ||
} | ||
var textContent = startContainer.textContent; | ||
function getWordPosition(_x, _x2) { | ||
var _again = true; | ||
_function: while (_again) { | ||
var position = _x, | ||
diff = _x2; | ||
_again = false; | ||
var prevText = textContent[position - 1]; | ||
if (null == prevText || 0 === prevText.trim().length || 0 >= position || textContent.length < position) { | ||
return position; | ||
} else { | ||
_x = position + diff; | ||
_x2 = diff; | ||
_again = true; | ||
prevText = undefined; | ||
continue _function; | ||
} | ||
} | ||
} | ||
this.wordStart = getWordPosition(startOffset + initialDiff, -1); | ||
this.wordEnd = getWordPosition(startOffset + initialDiff, 1) - 1; | ||
this.word = textContent.slice(this.wordStart, this.wordEnd); | ||
this.trigger = this.word.slice(0, 1); | ||
this.triggerClassName = this.triggerClassNameMap[this.trigger]; | ||
this.activeTriggerClassName = this.activeTriggerClassNameMap[this.trigger]; | ||
// | ||
this.extraTriggerClassName = this.extraTriggerClassNameMap[this.trigger]; | ||
this.extraActiveTriggerClassName = this.extraActiveTriggerClassNameMap[this.trigger]; | ||
}, | ||
showPanel: function showPanel() { | ||
if (!this.mentionPanel.classList.contains("medium-editor-mention-panel-active")) { | ||
this.activatePanel(); | ||
this.wrapWordInMentionAt(); | ||
} | ||
this.positionPanel(); | ||
this.updatePanelContent(); | ||
}, | ||
activatePanel: function activatePanel() { | ||
this.mentionPanel.classList.add("medium-editor-mention-panel-active"); | ||
if (this.extraActivePanelClassName || this.extraActiveClassName) { | ||
this.mentionPanel.classList.add(this.extraActivePanelClassName || this.extraActiveClassName); | ||
} | ||
}, | ||
wrapWordInMentionAt: function wrapWordInMentionAt() { | ||
var selection = this.document.getSelection(); | ||
if (!selection.rangeCount) { | ||
return; | ||
} | ||
// http://stackoverflow.com/a/6328906/1458162 | ||
var range = selection.getRangeAt(0).cloneRange(); | ||
if (range.startContainer.parentNode.classList.contains(this.triggerClassName)) { | ||
this.activeMentionAt = range.startContainer.parentNode; | ||
} else { | ||
range.setStart(range.startContainer, this.wordStart); | ||
range.setEnd(range.startContainer, Math.min(this.wordEnd, range.startContainer.textContent.length)); | ||
// Instead, insert our own version of it. | ||
// TODO: Not sure why, but using <span> tag doens't work here | ||
var element = this.document.createElement(this.tagName); | ||
element.classList.add(this.triggerClassName); | ||
if (this.extraTriggerClassName) { | ||
element.classList.add(this.extraTriggerClassName); | ||
} | ||
this.activeMentionAt = element; | ||
// | ||
range.surroundContents(element); | ||
selection.removeAllRanges(); | ||
selection.addRange(range); | ||
// | ||
_mediumEditor2["default"].selection.select(this.document, this.activeMentionAt.firstChild, this.word.length); | ||
} | ||
this.activeMentionAt.classList.add(this.activeTriggerClassName); | ||
if (this.extraActiveTriggerClassName) { | ||
this.activeMentionAt.classList.add(this.extraActiveTriggerClassName); | ||
} | ||
}, | ||
positionPanel: function positionPanel() { | ||
var _activeMentionAt$getBoundingClientRect = this.activeMentionAt.getBoundingClientRect(); | ||
var bottom = _activeMentionAt$getBoundingClientRect.bottom; | ||
var left = _activeMentionAt$getBoundingClientRect.left; | ||
var width = _activeMentionAt$getBoundingClientRect.width; | ||
var _window = this.window; | ||
var pageXOffset = _window.pageXOffset; | ||
var pageYOffset = _window.pageYOffset; | ||
this.mentionPanel.style.top = pageYOffset + bottom + "px"; | ||
this.mentionPanel.style.left = pageXOffset + left + width + "px"; | ||
}, | ||
updatePanelContent: function updatePanelContent() { | ||
this.renderPanelContent(this.mentionPanel, this.word, this.handleSelectMention.bind(this)); | ||
}, | ||
handleSelectMention: function handleSelectMention(seletedText) { | ||
if (seletedText) { | ||
var textNode = this.activeMentionAt.firstChild; | ||
textNode.textContent = seletedText; | ||
_mediumEditor2["default"].selection.select(this.document, textNode, seletedText.length); | ||
// | ||
this.hidePanel(false); | ||
} else { | ||
this.hidePanel(false); | ||
} | ||
this.mentionPanel.style.top = pageYOffset + bottom + "px"; | ||
this.mentionPanel.style.left = pageXOffset + left + width + "px"; | ||
}, | ||
updatePanelContent: function updatePanelContent() { | ||
this.renderPanelContent(this.mentionPanel, this.word, this.handleSelectMention.bind(this)); | ||
}, | ||
handleSelectMention: function handleSelectMention(seletedText) { | ||
if (seletedText) { | ||
var textNode = this.activeMentionAt.firstChild; | ||
textNode.textContent = seletedText; | ||
_mediumEditor2.default.selection.select(this.document, textNode, seletedText.length); | ||
// | ||
this.hidePanel(false); | ||
} else { | ||
this.hidePanel(false); | ||
} | ||
} | ||
}); | ||
exports.TCMention = TCMention; | ||
exports["default"] = TCMention; | ||
exports.default = TCMention; |
@@ -1,2 +0,2 @@ | ||
!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("MediumEditor"));else if("function"==typeof define&&define.amd)define(["MediumEditor"],e);else{var i=e("object"==typeof exports?require("MediumEditor"):t.MediumEditor);for(var n in i)("object"==typeof exports?exports:t)[n]=i[n]}}(this,function(t){return function(t){function e(n){if(i[n])return i[n].exports;var a=i[n]={exports:{},id:n,loaded:!1};return t[n].call(a.exports,a,a.exports,e),a.loaded=!0,a.exports}var i={};return e.m=t,e.c=i,e.p="",e(0)}([function(t,e,i){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function a(t){return t[t.length-1]}function s(t,e){var i,n,a=t.parentNode;for(o["default"].util.unwrap(t,e),n=a.lastChild;i=n.previousSibling;)3===n.nodeType&&3===i.nodeType&&(i.textContent+=n.textContent,a.removeChild(n)),n=i}Object.defineProperty(e,"__esModule",{value:!0}),e.unwrapForTextNode=s;var r=i(1),o=n(r),l=37;e.LEFT_ARROW_KEYCODE=l;var h=o["default"].Extension.extend({name:"mention",extraClassName:"",extraActiveClassName:"",extraPanelClassName:"",extraActivePanelClassName:"",extraTriggerClassNameMap:{},extraActiveTriggerClassNameMap:{},tagName:"strong",renderPanelContent:function(){},destroyPanelContent:function(){},activeTriggerList:["@"],triggerClassNameMap:{"#":"medium-editor-mention-hash","@":"medium-editor-mention-at"},activeTriggerClassNameMap:{"#":"medium-editor-mention-hash-active","@":"medium-editor-mention-at-active"},hideOnBlurDelay:300,init:function(){this.initMentionPanel(),this.attachEventHandlers()},destroy:function(){this.mentionPanel&&(this.mentionPanel.parentNode&&(this.destroyPanelContent(this.mentionPanel),this.mentionPanel.parentNode.removeChild(this.mentionPanel)),delete this.mentionPanel)},initMentionPanel:function(){var t=this.document.createElement("div");t.classList.add("medium-editor-mention-panel"),(this.extraPanelClassName||this.extraClassName)&&t.classList.add(this.extraPanelClassName||this.extraClassName),this.getEditorOption("elementsContainer").appendChild(t),this.mentionPanel=t},attachEventHandlers:function(){null!=this.hideOnBlurDelay&&(this.subscribe("blur",this.handleBlur.bind(this)),this.subscribe("focus",this.handleFocus.bind(this))),this.subscribe("editableKeyup",this.handleKeyup.bind(this))},handleBlur:function(){var t=this;null!=this.hideOnBlurDelay&&(this.hideOnBlurDelayId=setTimeout(function(){t.hidePanel(!1)},this.hideOnBlurDelay))},handleFocus:function(){this.hideOnBlurDelayId&&(clearTimeout(this.hideOnBlurDelayId),this.hideOnBlurDelayId=null)},handleKeyup:function(t){var e=o["default"].util.getKeyCode(t),i=e===o["default"].util.keyCode.SPACE;this.getWordFromSelection(t.target,i?-1:0),!i&&-1!==this.activeTriggerList.indexOf(this.trigger)&&1<this.word.length?this.showPanel():this.hidePanel(e===l)},hidePanel:function(t){if(this.mentionPanel.classList.remove("medium-editor-mention-panel-active"),(this.extraActivePanelClassName||this.extraActiveClassName)&&this.mentionPanel.classList.remove(this.extraActivePanelClassName||this.extraActiveClassName),this.activeMentionAt&&(this.activeMentionAt.classList.remove(this.activeTriggerClassName),this.extraActiveTriggerClassName&&this.activeMentionAt.classList.remove(this.extraActiveTriggerClassName)),this.activeMentionAt){var e=this.activeMentionAt,i=e.parentNode,n=e.previousSibling,r=e.nextSibling,l=e.firstChild,h=t?n:r,d=void 0;h?3!==h.nodeType?(d=this.document.createTextNode(""),i.insertBefore(d,h)):d=h:(d=this.document.createTextNode(""),i.appendChild(d));var c=a(l.textContent),m=0===c.trim().length;m?(l.textContent=l.textContent.substr(0,l.textContent.length-1),d.textContent=""+c+d.textContent):0===d.textContent.length&&1<l.textContent.length&&(d.textContent=" "),t?o["default"].selection.select(this.document,d,d.length):o["default"].selection.select(this.document,d,Math.min(d.length,1)),1>=l.textContent.length&&(this.base.saveSelection(),s(this.activeMentionAt,this.document),this.base.restoreSelection()),this.activeMentionAt=null}},getWordFromSelection:function(t,e){function i(t,e){for(var i=!0;i;){var n=t,a=e;i=!1;var s=l[n-1];if(null==s||0===s.trim().length||0>=n||l.length<n)return n;t=n+a,e=a,i=!0,s=void 0}}var n=o["default"].selection.getSelectionRange(this.document),a=n.startContainer,s=n.startOffset,r=n.endContainer;n.endOffset;if(a===r){var l=a.textContent;this.wordStart=i(s+e,-1),this.wordEnd=i(s+e,1)-1,this.word=l.slice(this.wordStart,this.wordEnd),this.trigger=this.word.slice(0,1),this.triggerClassName=this.triggerClassNameMap[this.trigger],this.activeTriggerClassName=this.activeTriggerClassNameMap[this.trigger],this.extraTriggerClassName=this.extraTriggerClassNameMap[this.trigger],this.extraActiveTriggerClassName=this.extraActiveTriggerClassNameMap[this.trigger]}},showPanel:function(){this.mentionPanel.classList.contains("medium-editor-mention-panel-active")||(this.activatePanel(),this.wrapWordInMentionAt()),this.positionPanel(),this.updatePanelContent()},activatePanel:function(){this.mentionPanel.classList.add("medium-editor-mention-panel-active"),(this.extraActivePanelClassName||this.extraActiveClassName)&&this.mentionPanel.classList.add(this.extraActivePanelClassName||this.extraActiveClassName)},wrapWordInMentionAt:function(){var t=this.document.getSelection();if(t.rangeCount){var e=t.getRangeAt(0).cloneRange();if(e.startContainer.parentNode.classList.contains(this.triggerClassName))this.activeMentionAt=e.startContainer.parentNode;else{e.setStart(e.startContainer,this.wordStart),e.setEnd(e.startContainer,Math.min(this.wordEnd,e.startContainer.textContent.length));var i=this.document.createElement(this.tagName);i.classList.add(this.triggerClassName),this.extraTriggerClassName&&i.classList.add(this.extraTriggerClassName),this.activeMentionAt=i,e.surroundContents(i),t.removeAllRanges(),t.addRange(e),o["default"].selection.select(this.document,this.activeMentionAt.firstChild,this.word.length)}this.activeMentionAt.classList.add(this.activeTriggerClassName),this.extraActiveTriggerClassName&&this.activeMentionAt.classList.add(this.extraActiveTriggerClassName)}},positionPanel:function(){var t=this.activeMentionAt.getBoundingClientRect(),e=t.bottom,i=t.left,n=t.width,a=this.window,s=a.pageXOffset,r=a.pageYOffset;this.mentionPanel.style.top=r+e+"px",this.mentionPanel.style.left=s+i+n+"px"},updatePanelContent:function(){this.renderPanelContent(this.mentionPanel,this.word,this.handleSelectMention.bind(this))},handleSelectMention:function(t){if(t){var e=this.activeMentionAt.firstChild;e.textContent=t,o["default"].selection.select(this.document,e,t.length),this.hidePanel(!1)}else this.hidePanel(!1)}});e.TCMention=h,e["default"]=h},function(e,i){e.exports=t}])}); | ||
!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("MediumEditor"));else if("function"==typeof define&&define.amd)define(["MediumEditor"],e);else{var i=e("object"==typeof exports?require("MediumEditor"):t.MediumEditor);for(var n in i)("object"==typeof exports?exports:t)[n]=i[n]}}(this,function(t){return function(t){function e(n){if(i[n])return i[n].exports;var a=i[n]={exports:{},id:n,loaded:!1};return t[n].call(a.exports,a,a.exports,e),a.loaded=!0,a.exports}var i={};return e.m=t,e.c=i,e.p="",e(0)}([function(t,e,i){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function a(t){return t[t.length-1]}function s(t,e){var i=t.parentNode;o["default"].util.unwrap(t,e);for(var n=i.lastChild,a=n.previousSibling;a;)3===n.nodeType&&3===a.nodeType&&(a.textContent+=n.textContent,i.removeChild(n)),n=a,a=n.previousSibling}Object.defineProperty(e,"__esModule",{value:!0}),e.TCMention=e.LEFT_ARROW_KEYCODE=void 0,e.unwrapForTextNode=s;var r=i(1),o=n(r),l=e.LEFT_ARROW_KEYCODE=37,h=e.TCMention=o["default"].Extension.extend({name:"mention",extraClassName:"",extraActiveClassName:"",extraPanelClassName:"",extraActivePanelClassName:"",extraTriggerClassNameMap:{},extraActiveTriggerClassNameMap:{},tagName:"strong",renderPanelContent:function(){},destroyPanelContent:function(){},activeTriggerList:["@"],triggerClassNameMap:{"#":"medium-editor-mention-hash","@":"medium-editor-mention-at"},activeTriggerClassNameMap:{"#":"medium-editor-mention-hash-active","@":"medium-editor-mention-at-active"},hideOnBlurDelay:300,init:function(){this.initMentionPanel(),this.attachEventHandlers()},destroy:function(){this.mentionPanel&&(this.mentionPanel.parentNode&&(this.destroyPanelContent(this.mentionPanel),this.mentionPanel.parentNode.removeChild(this.mentionPanel)),delete this.mentionPanel)},initMentionPanel:function(){var t=this.document.createElement("div");t.classList.add("medium-editor-mention-panel"),(this.extraPanelClassName||this.extraClassName)&&t.classList.add(this.extraPanelClassName||this.extraClassName),this.getEditorOption("elementsContainer").appendChild(t),this.mentionPanel=t},attachEventHandlers:function(){null!==this.hideOnBlurDelay&&void 0!==this.hideOnBlurDelay&&(this.subscribe("blur",this.handleBlur.bind(this)),this.subscribe("focus",this.handleFocus.bind(this))),this.subscribe("editableKeyup",this.handleKeyup.bind(this))},handleBlur:function(){var t=this;null!==this.hideOnBlurDelay&&void 0!==this.hideOnBlurDelay&&(this.hideOnBlurDelayId=setTimeout(function(){t.hidePanel(!1)},this.hideOnBlurDelay))},handleFocus:function(){this.hideOnBlurDelayId&&(clearTimeout(this.hideOnBlurDelayId),this.hideOnBlurDelayId=null)},handleKeyup:function(t){var e=o["default"].util.getKeyCode(t),i=e===o["default"].util.keyCode.SPACE;this.getWordFromSelection(t.target,i?-1:0),!i&&-1!==this.activeTriggerList.indexOf(this.trigger)&&this.word.length>1?this.showPanel():this.hidePanel(e===l)},hidePanel:function(t){this.mentionPanel.classList.remove("medium-editor-mention-panel-active");var e=this.extraActivePanelClassName||this.extraActiveClassName;if(e&&this.mentionPanel.classList.remove(e),this.activeMentionAt&&(this.activeMentionAt.classList.remove(this.activeTriggerClassName),this.extraActiveTriggerClassName&&this.activeMentionAt.classList.remove(this.extraActiveTriggerClassName)),this.activeMentionAt){var i=this.activeMentionAt,n=i.parentNode,r=i.previousSibling,l=i.nextSibling,h=i.firstChild,d=t?r:l,c=void 0;d?3!==d.nodeType?(c=this.document.createTextNode(""),n.insertBefore(c,d)):c=d:(c=this.document.createTextNode(""),n.appendChild(c));var u=a(h.textContent),m=0===u.trim().length;if(m){var g=h.textContent;h.textContent=g.substr(0,g.length-1),c.textContent=""+u+c.textContent}else 0===c.textContent.length&&h.textContent.length>1&&(c.textContent=" ");t?o["default"].selection.select(this.document,c,c.length):o["default"].selection.select(this.document,c,Math.min(c.length,1)),h.textContent.length<=1&&(this.base.saveSelection(),s(this.activeMentionAt,this.document),this.base.restoreSelection()),this.activeMentionAt=null}},getWordFromSelection:function(t,e){function i(t,e){var n=l[t-1];return null===n||void 0===n?t:0===n.trim().length||0>=t||l.length<t?t:i(t+e,e)}var n=o["default"].selection.getSelectionRange(this.document),a=n.startContainer,s=n.startOffset,r=n.endContainer;if(a===r){var l=a.textContent;this.wordStart=i(s+e,-1),this.wordEnd=i(s+e,1)-1,this.word=l.slice(this.wordStart,this.wordEnd),this.trigger=this.word.slice(0,1),this.triggerClassName=this.triggerClassNameMap[this.trigger],this.activeTriggerClassName=this.activeTriggerClassNameMap[this.trigger],this.extraTriggerClassName=this.extraTriggerClassNameMap[this.trigger],this.extraActiveTriggerClassName=this.extraActiveTriggerClassNameMap[this.trigger]}},showPanel:function(){this.mentionPanel.classList.contains("medium-editor-mention-panel-active")||(this.activatePanel(),this.wrapWordInMentionAt()),this.positionPanel(),this.updatePanelContent()},activatePanel:function(){this.mentionPanel.classList.add("medium-editor-mention-panel-active"),(this.extraActivePanelClassName||this.extraActiveClassName)&&this.mentionPanel.classList.add(this.extraActivePanelClassName||this.extraActiveClassName)},wrapWordInMentionAt:function(){var t=this.document.getSelection();if(t.rangeCount){var e=t.getRangeAt(0).cloneRange();if(e.startContainer.parentNode.classList.contains(this.triggerClassName))this.activeMentionAt=e.startContainer.parentNode;else{var i=Math.min(this.wordEnd,e.startContainer.textContent.length);e.setStart(e.startContainer,this.wordStart),e.setEnd(e.startContainer,i);var n=this.document.createElement(this.tagName);n.classList.add(this.triggerClassName),this.extraTriggerClassName&&n.classList.add(this.extraTriggerClassName),this.activeMentionAt=n,e.surroundContents(n),t.removeAllRanges(),t.addRange(e),o["default"].selection.select(this.document,this.activeMentionAt.firstChild,this.word.length)}this.activeMentionAt.classList.add(this.activeTriggerClassName),this.extraActiveTriggerClassName&&this.activeMentionAt.classList.add(this.extraActiveTriggerClassName)}},positionPanel:function(){var t=this.activeMentionAt.getBoundingClientRect(),e=t.bottom,i=t.left,n=t.width,a=this.window,s=a.pageXOffset,r=a.pageYOffset;this.mentionPanel.style.top=r+e+"px",this.mentionPanel.style.left=s+i+n+"px"},updatePanelContent:function(){this.renderPanelContent(this.mentionPanel,this.word,this.handleSelectMention.bind(this))},handleSelectMention:function(t){if(t){var e=this.activeMentionAt.firstChild;e.textContent=t,o["default"].selection.select(this.document,e,t.length),this.hidePanel(!1)}else this.hidePanel(!1)}});e["default"]=h},function(e,i){e.exports=t}])}); | ||
//# sourceMappingURL=index.min.js.map |
{ | ||
"name": "medium-editor-tc-mention", | ||
"version": "2.1.1", | ||
"version": "2.2.0", | ||
"description": "MediumEditor extension for mention panels like @username or #tagging", | ||
@@ -14,14 +14,15 @@ "main": "lib/index.js", | ||
"prebuild": "npm run lint && npm run clean", | ||
"build:babel": "babel src --out-dir lib", | ||
"build:webpack": "webpack -p && rimraf lib/mention-panel.min.js lib/mention-panel.min.js.map lib/mention-panel.min.css.map", | ||
"build:babel": "cross-env NODE_ENV=production babel src --out-dir lib", | ||
"build:webpack": "cross-env NODE_ENV=production webpack --config webpack.config.babel.js -p", | ||
"postbuild:webpack": "rimraf lib/mention-panel.min.js lib/mention-panel.min.js.map lib/mention-panel.min.css.map", | ||
"build": "npm run build:babel && npm run build:webpack", | ||
"lint": "eslint src", | ||
"lint": "cross-env NODE_ENV=test eslint src", | ||
"pretest:cov": "npm run lint", | ||
"pretest": "npm run lint", | ||
"test:cov": "babel-node ./node_modules/.bin/isparta cover --report lcov _mocha -- $npm_package_config_mocha", | ||
"test:cov": "cross-env NODE_ENV=test babel-node ./node_modules/.bin/isparta cover --report lcov _mocha -- $npm_package_config_mocha", | ||
"test:watch": "npm test -- --watch", | ||
"test": "mocha $npm_package_config_mocha" | ||
"test": "cross-env NODE_ENV=test mocha $npm_package_config_mocha" | ||
}, | ||
"config": { | ||
"mocha": "--compilers js:babel/register ./src/**/__tests__/*.spec.js" | ||
"mocha": "--compilers js:babel-register ./src/**/__tests__/*.spec.js --require ./src/__tests__/setup.js" | ||
}, | ||
@@ -52,22 +53,31 @@ "repository": { | ||
"devDependencies": { | ||
"babel": "^5.8.23", | ||
"babel-core": "^5.8.25", | ||
"babel-eslint": "^4.1.3", | ||
"babel-loader": "^5.3.2", | ||
"codeclimate-test-reporter": "^0.1.1", | ||
"css-loader": "^0.19.0", | ||
"eslint": "^1.6.0", | ||
"expect": "^1.12.2", | ||
"extract-text-webpack-plugin": "^0.8.2", | ||
"isparta": "^3.1.0", | ||
"istanbul": "^0.3.22", | ||
"jsdom": "^6.5.1", | ||
"medium-editor": "^5.8.3", | ||
"mocha": "^2.3.3", | ||
"mocha-jsdom": "^1.0.0", | ||
"node-sass": "^3.3.3", | ||
"rimraf": "^2.4.3", | ||
"sass-loader": "^3.0.0", | ||
"style-loader": "^0.12.4", | ||
"webpack": "^1.12.2" | ||
"babel-cli": "^6.4.5", | ||
"babel-core": "^6.4.5", | ||
"babel-eslint": "^5.0.0-beta6", | ||
"babel-loader": "^6.2.1", | ||
"babel-plugin-transform-flow-comments": "^6.4.0", | ||
"babel-plugin-typecheck": "^3.6.1", | ||
"babel-preset-es2015": "^6.3.13", | ||
"babel-preset-react": "^6.3.13", | ||
"babel-preset-stage-0": "^6.3.13", | ||
"babel-register": "^6.4.3", | ||
"codeclimate-test-reporter": "^0.3.0", | ||
"cross-env": "^1.0.7", | ||
"css-loader": "^0.23.1", | ||
"eslint": "^1.10.3", | ||
"eslint-config-airbnb": "^4.0.0", | ||
"eslint-plugin-react": "^3.16.1", | ||
"expect": "^1.13.4", | ||
"extract-text-webpack-plugin": "^1.0.1", | ||
"isparta": "^4.0.0", | ||
"istanbul": "^0.4.2", | ||
"jsdom": "^7.2.2", | ||
"medium-editor": "^5.13.0", | ||
"mocha": "^2.3.4", | ||
"node-sass": "^3.4.2", | ||
"rimraf": "^2.5.1", | ||
"sass-loader": "^3.1.2", | ||
"style-loader": "^0.13.0", | ||
"tomchentw-npm-dev": "^3.2.0", | ||
"webpack": "^1.12.12" | ||
}, | ||
@@ -74,0 +84,0 @@ "dependencies": {}, |
@@ -0,1 +1,3 @@ | ||
/* eslint-disable prefer-arrow-callback */ | ||
import { | ||
@@ -5,12 +7,6 @@ default as expect, | ||
import { | ||
default as jsdom, | ||
} from "mocha-jsdom"; | ||
describe(`index`, function describeIndex() { | ||
it(`should be exported`, function it() { | ||
const Module = require(`../index`); | ||
describe("index", () => { | ||
jsdom(); | ||
it("should be exported", () => { | ||
const Module = require("../index"); | ||
expect(Module.default).toExist(); | ||
@@ -17,0 +13,0 @@ expect(Module.TCMention).toExist(); |
569
src/index.js
@@ -1,5 +0,7 @@ | ||
import MediumEditor from "medium-editor"; | ||
import { | ||
default as MediumEditor, | ||
} from "medium-editor"; | ||
function last (text) { | ||
return text[text.length - 1]; | ||
function last(text) { | ||
return text[text.length - 1]; | ||
} | ||
@@ -9,318 +11,335 @@ | ||
export function unwrapForTextNode (el, doc) { | ||
var parentNode = el.parentNode, | ||
prevNode, | ||
currentNode; | ||
MediumEditor.util.unwrap(el, doc); | ||
export function unwrapForTextNode(el, doc) { | ||
const parentNode = el.parentNode; | ||
MediumEditor.util.unwrap(el, doc); | ||
// Merge textNode | ||
currentNode = parentNode.lastChild; | ||
while (prevNode = currentNode.previousSibling) { | ||
if (3 === currentNode.nodeType && 3 === prevNode.nodeType) { | ||
prevNode.textContent += currentNode.textContent; | ||
parentNode.removeChild(currentNode); | ||
} | ||
currentNode = prevNode; | ||
let currentNode = parentNode.lastChild; | ||
let prevNode = currentNode.previousSibling; | ||
while (prevNode) { | ||
if (currentNode.nodeType === 3 && prevNode.nodeType === 3) { | ||
prevNode.textContent += currentNode.textContent; | ||
parentNode.removeChild(currentNode); | ||
} | ||
currentNode = prevNode; | ||
prevNode = currentNode.previousSibling; | ||
} | ||
} | ||
export const TCMention = MediumEditor.Extension.extend({ | ||
name: `mention`, | ||
name: `mention`, | ||
/* @deprecated: use extraPanelClassName. Will remove in next major (3.0.0) release | ||
* extraClassName: [string] | ||
* | ||
* Extra className to be added with the `medium-editor-mention-panel` element. | ||
*/ | ||
extraClassName: ``, | ||
/* @deprecated: use extraPanelClassName. Will remove in next major (3.0.0) release | ||
* extraClassName: [string] | ||
* | ||
* Extra className to be added with the `medium-editor-mention-panel` element. | ||
*/ | ||
extraClassName: ``, | ||
/* @deprecated: use extraActivePanelClassName. Will remove in next major (3.0.0) release | ||
* extraActiveClassName: [string] | ||
* | ||
* Extra active className to be added with the `medium-editor-mention-panel-active` element. | ||
*/ | ||
extraActiveClassName: ``, | ||
/* @deprecated: use extraActivePanelClassName. Will remove in next major (3.0.0) release | ||
* extraActiveClassName: [string] | ||
* | ||
* Extra active className to be added with the `medium-editor-mention-panel-active` element. | ||
*/ | ||
extraActiveClassName: ``, | ||
/* extraPanelClassName: [string] | ||
* | ||
* Extra className to be added with the `medium-editor-mention-panel` element. | ||
*/ | ||
extraPanelClassName: ``, | ||
/* extraPanelClassName: [string] | ||
* | ||
* Extra className to be added with the `medium-editor-mention-panel` element. | ||
*/ | ||
extraPanelClassName: ``, | ||
/* extraActivePanelClassName: [string] | ||
* | ||
* Extra active className to be added with the `medium-editor-mention-panel-active` element. | ||
*/ | ||
extraActivePanelClassName: ``, | ||
/* extraActivePanelClassName: [string] | ||
* | ||
* Extra active className to be added with the `medium-editor-mention-panel-active` element. | ||
*/ | ||
extraActivePanelClassName: ``, | ||
extraTriggerClassNameMap: {}, | ||
extraTriggerClassNameMap: {}, | ||
extraActiveTriggerClassNameMap: {}, | ||
extraActiveTriggerClassNameMap: {}, | ||
/* tagName: [string] | ||
* | ||
* Element tag name that would indicate that this mention. It will have | ||
* `medium-editor-mention-at` className applied on it. | ||
*/ | ||
tagName: `strong`, | ||
/* tagName: [string] | ||
* | ||
* Element tag name that would indicate that this mention. It will have | ||
* `medium-editor-mention-at` className applied on it. | ||
*/ | ||
tagName: `strong`, | ||
/* renderPanelContent: [function (panelEl: dom, currentMentionText: string, selectMentionCallback: function)] | ||
* | ||
* Render function that used to create the content of the panel when panel is show. | ||
* | ||
* @params panelEl: DOM element of the panel. | ||
* | ||
* @params currentMentionText: Often used as query criteria. e.g. @medium | ||
* | ||
* @params selectMentionCallback: | ||
* callback used in customized panel content. | ||
* | ||
* When called with null, it tells the Mention plugin to close the panel. | ||
* e.g. selectMentionCallback(null); | ||
* | ||
* When called with text, it tells the Mention plugin that the text is selected by the user. | ||
* e.g. selectMentionCallback("@mediumrocks") | ||
*/ | ||
renderPanelContent: () => {}, | ||
/* renderPanelContent: [ | ||
* function (panelEl: dom, currentMentionText: string, selectMentionCallback: function) | ||
* ] | ||
* | ||
* Render function that used to create the content of the panel when panel is show. | ||
* | ||
* @params panelEl: DOM element of the panel. | ||
* | ||
* @params currentMentionText: Often used as query criteria. e.g. @medium | ||
* | ||
* @params selectMentionCallback: | ||
* callback used in customized panel content. | ||
* | ||
* When called with null, it tells the Mention plugin to close the panel. | ||
* e.g. selectMentionCallback(null); | ||
* | ||
* When called with text, it tells the Mention plugin that the text is selected by the user. | ||
* e.g. selectMentionCallback("@mediumrocks") | ||
*/ | ||
renderPanelContent() {}, | ||
/* destroyPanelContent: [function (panelEl: dom)] | ||
* | ||
* Destroy function to remove any contents rendered by renderPanelContent before panelEl being removed from the document. | ||
* | ||
* @params panelEl: DOM element of the panel. | ||
*/ | ||
destroyPanelContent: () => {}, | ||
/* destroyPanelContent: [function (panelEl: dom)] | ||
* | ||
* Destroy function to remove any contents rendered by renderPanelContent | ||
* before panelEl being removed from the document. | ||
* | ||
* @params panelEl: DOM element of the panel. | ||
*/ | ||
destroyPanelContent() {}, | ||
activeTriggerList: [`@`], | ||
activeTriggerList: [`@`], | ||
triggerClassNameMap: { | ||
"#": `medium-editor-mention-hash`, | ||
"@": `medium-editor-mention-at`, | ||
}, | ||
triggerClassNameMap: { | ||
"#": `medium-editor-mention-hash`, | ||
"@": `medium-editor-mention-at`, | ||
}, | ||
activeTriggerClassNameMap: { | ||
"#": `medium-editor-mention-hash-active`, | ||
"@": `medium-editor-mention-at-active`, | ||
}, | ||
activeTriggerClassNameMap: { | ||
"#": `medium-editor-mention-hash-active`, | ||
"@": `medium-editor-mention-at-active`, | ||
}, | ||
hideOnBlurDelay: 300, | ||
hideOnBlurDelay: 300, | ||
init () { | ||
this.initMentionPanel(); | ||
this.attachEventHandlers(); | ||
}, | ||
init() { | ||
this.initMentionPanel(); | ||
this.attachEventHandlers(); | ||
}, | ||
destroy () { | ||
if (this.mentionPanel) { | ||
if (this.mentionPanel.parentNode) { | ||
this.destroyPanelContent(this.mentionPanel); | ||
this.mentionPanel.parentNode.removeChild(this.mentionPanel); | ||
} | ||
delete this.mentionPanel; | ||
} | ||
}, | ||
destroy() { | ||
if (this.mentionPanel) { | ||
if (this.mentionPanel.parentNode) { | ||
this.destroyPanelContent(this.mentionPanel); | ||
this.mentionPanel.parentNode.removeChild(this.mentionPanel); | ||
} | ||
delete this.mentionPanel; | ||
} | ||
}, | ||
initMentionPanel () { | ||
const el = this.document.createElement(`div`); | ||
initMentionPanel() { | ||
const el = this.document.createElement(`div`); | ||
el.classList.add(`medium-editor-mention-panel`); | ||
if (this.extraPanelClassName || this.extraClassName) { | ||
el.classList.add(this.extraPanelClassName || this.extraClassName); | ||
} | ||
el.classList.add(`medium-editor-mention-panel`); | ||
if (this.extraPanelClassName || this.extraClassName) { | ||
el.classList.add(this.extraPanelClassName || this.extraClassName); | ||
} | ||
this.getEditorOption(`elementsContainer`).appendChild(el); | ||
this.getEditorOption(`elementsContainer`).appendChild(el); | ||
this.mentionPanel = el; | ||
}, | ||
this.mentionPanel = el; | ||
}, | ||
attachEventHandlers () { | ||
if (null != this.hideOnBlurDelay) { | ||
// for hideOnBlurDelay, the panel should hide after blur event | ||
this.subscribe(`blur`, ::this.handleBlur); | ||
// and clear out hide timeout if focus again | ||
this.subscribe(`focus`, ::this.handleFocus); | ||
} | ||
// if the editor changes its content, we have to show or hide the panel | ||
this.subscribe(`editableKeyup`, ::this.handleKeyup); | ||
}, | ||
attachEventHandlers() { | ||
if (this.hideOnBlurDelay !== null && this.hideOnBlurDelay !== undefined) { | ||
// for hideOnBlurDelay, the panel should hide after blur event | ||
this.subscribe(`blur`, ::this.handleBlur); | ||
// and clear out hide timeout if focus again | ||
this.subscribe(`focus`, ::this.handleFocus); | ||
} | ||
// if the editor changes its content, we have to show or hide the panel | ||
this.subscribe(`editableKeyup`, ::this.handleKeyup); | ||
}, | ||
handleBlur () { | ||
if (null != this.hideOnBlurDelay) { | ||
this.hideOnBlurDelayId = setTimeout(() => { | ||
this.hidePanel(false); | ||
}, this.hideOnBlurDelay); | ||
} | ||
}, | ||
handleBlur() { | ||
if (this.hideOnBlurDelay !== null && this.hideOnBlurDelay !== undefined) { | ||
this.hideOnBlurDelayId = setTimeout(() => { | ||
this.hidePanel(false); | ||
}, this.hideOnBlurDelay); | ||
} | ||
}, | ||
handleFocus () { | ||
if (this.hideOnBlurDelayId) { | ||
clearTimeout(this.hideOnBlurDelayId); | ||
this.hideOnBlurDelayId = null; | ||
} | ||
}, | ||
handleFocus() { | ||
if (this.hideOnBlurDelayId) { | ||
clearTimeout(this.hideOnBlurDelayId); | ||
this.hideOnBlurDelayId = null; | ||
} | ||
}, | ||
handleKeyup (event) { | ||
const keyCode = MediumEditor.util.getKeyCode(event); | ||
const isSpace = keyCode === MediumEditor.util.keyCode.SPACE; | ||
this.getWordFromSelection(event.target, isSpace ? -1 : 0); | ||
handleKeyup(event) { | ||
const keyCode = MediumEditor.util.getKeyCode(event); | ||
const isSpace = keyCode === MediumEditor.util.keyCode.SPACE; | ||
this.getWordFromSelection(event.target, isSpace ? -1 : 0); | ||
if (!isSpace && -1 !== this.activeTriggerList.indexOf(this.trigger) && 1 < this.word.length) { | ||
this.showPanel(); | ||
} else { | ||
this.hidePanel(keyCode === LEFT_ARROW_KEYCODE); | ||
} | ||
}, | ||
if (!isSpace && this.activeTriggerList.indexOf(this.trigger) !== -1 && this.word.length > 1) { | ||
this.showPanel(); | ||
} else { | ||
this.hidePanel(keyCode === LEFT_ARROW_KEYCODE); | ||
} | ||
}, | ||
hidePanel (isArrowTowardsLeft) { | ||
this.mentionPanel.classList.remove(`medium-editor-mention-panel-active`); | ||
if (this.extraActivePanelClassName || this.extraActiveClassName) { | ||
this.mentionPanel.classList.remove(this.extraActivePanelClassName || this.extraActiveClassName); | ||
} | ||
if (this.activeMentionAt) { | ||
this.activeMentionAt.classList.remove(this.activeTriggerClassName); | ||
if (this.extraActiveTriggerClassName) { | ||
this.activeMentionAt.classList.remove(this.extraActiveTriggerClassName); | ||
} | ||
} | ||
if (this.activeMentionAt) { | ||
// http://stackoverflow.com/a/27004526/1458162 | ||
const {parentNode, previousSibling, nextSibling, firstChild} = this.activeMentionAt; | ||
const siblingNode = isArrowTowardsLeft ? previousSibling : nextSibling; | ||
let textNode; | ||
if (!siblingNode) { | ||
textNode = this.document.createTextNode(``); | ||
parentNode.appendChild(textNode); | ||
} else if (3 !== siblingNode.nodeType) { | ||
textNode = this.document.createTextNode(``); | ||
parentNode.insertBefore(textNode, siblingNode); | ||
} else { | ||
textNode = siblingNode; | ||
} | ||
const lastEmptyWord = last(firstChild.textContent); | ||
const hasLastEmptyWord = 0 === lastEmptyWord.trim().length; | ||
if (hasLastEmptyWord) { | ||
firstChild.textContent = firstChild.textContent.substr(0, firstChild.textContent.length-1); | ||
textNode.textContent = `${ lastEmptyWord }${ textNode.textContent }`; | ||
} else { | ||
if (0 === textNode.textContent.length && 1 < firstChild.textContent.length) { | ||
textNode.textContent = `\u00A0`; | ||
} | ||
} | ||
if (isArrowTowardsLeft) { | ||
MediumEditor.selection.select(this.document, textNode, textNode.length); | ||
} else { | ||
MediumEditor.selection.select(this.document, textNode, Math.min(textNode.length, 1)); | ||
} | ||
if (1 >= firstChild.textContent.length) { | ||
// LIKE core#execAction | ||
this.base.saveSelection(); | ||
unwrapForTextNode(this.activeMentionAt, this.document); | ||
this.base.restoreSelection(); | ||
} | ||
// | ||
this.activeMentionAt = null; | ||
} | ||
}, | ||
hidePanel(isArrowTowardsLeft) { | ||
this.mentionPanel.classList.remove(`medium-editor-mention-panel-active`); | ||
const extraActivePanelClassName = this.extraActivePanelClassName || this.extraActiveClassName; | ||
getWordFromSelection (target, initialDiff) { | ||
const {startContainer, startOffset, endContainer, endOffset} = MediumEditor.selection.getSelectionRange(this.document); | ||
if (startContainer !== endContainer) { | ||
return; | ||
if (extraActivePanelClassName) { | ||
this.mentionPanel.classList.remove(extraActivePanelClassName); | ||
} | ||
if (this.activeMentionAt) { | ||
this.activeMentionAt.classList.remove(this.activeTriggerClassName); | ||
if (this.extraActiveTriggerClassName) { | ||
this.activeMentionAt.classList.remove(this.extraActiveTriggerClassName); | ||
} | ||
} | ||
if (this.activeMentionAt) { | ||
// http://stackoverflow.com/a/27004526/1458162 | ||
const { parentNode, previousSibling, nextSibling, firstChild } = this.activeMentionAt; | ||
const siblingNode = isArrowTowardsLeft ? previousSibling : nextSibling; | ||
let textNode; | ||
if (!siblingNode) { | ||
textNode = this.document.createTextNode(``); | ||
parentNode.appendChild(textNode); | ||
} else if (siblingNode.nodeType !== 3) { | ||
textNode = this.document.createTextNode(``); | ||
parentNode.insertBefore(textNode, siblingNode); | ||
} else { | ||
textNode = siblingNode; | ||
} | ||
const lastEmptyWord = last(firstChild.textContent); | ||
const hasLastEmptyWord = lastEmptyWord.trim().length === 0; | ||
if (hasLastEmptyWord) { | ||
const { textContent } = firstChild; | ||
firstChild.textContent = textContent.substr(0, textContent.length - 1); | ||
textNode.textContent = `${ lastEmptyWord }${ textNode.textContent }`; | ||
} else { | ||
if (textNode.textContent.length === 0 && firstChild.textContent.length > 1) { | ||
textNode.textContent = `\u00A0`; | ||
} | ||
const {textContent} = startContainer; | ||
} | ||
if (isArrowTowardsLeft) { | ||
MediumEditor.selection.select(this.document, textNode, textNode.length); | ||
} else { | ||
MediumEditor.selection.select(this.document, textNode, Math.min(textNode.length, 1)); | ||
} | ||
if (firstChild.textContent.length <= 1) { | ||
// LIKE core#execAction | ||
this.base.saveSelection(); | ||
unwrapForTextNode(this.activeMentionAt, this.document); | ||
this.base.restoreSelection(); | ||
} | ||
// | ||
this.activeMentionAt = null; | ||
} | ||
}, | ||
function getWordPosition (position, diff) { | ||
const prevText = textContent[position - 1]; | ||
if (null == prevText || 0 === prevText.trim().length || 0 >= position || textContent.length < position) { | ||
return position; | ||
} else { | ||
return getWordPosition(position + diff, diff); | ||
} | ||
} | ||
getWordFromSelection(target, initialDiff) { | ||
const { | ||
startContainer, | ||
startOffset, | ||
endContainer, | ||
} = MediumEditor.selection.getSelectionRange(this.document); | ||
if (startContainer !== endContainer) { | ||
return; | ||
} | ||
const { textContent } = startContainer; | ||
this.wordStart = getWordPosition(startOffset + initialDiff, -1); | ||
this.wordEnd = getWordPosition(startOffset + initialDiff, 1) - 1; | ||
this.word = textContent.slice(this.wordStart, this.wordEnd); | ||
this.trigger = this.word.slice(0, 1); | ||
this.triggerClassName = this.triggerClassNameMap[this.trigger]; | ||
this.activeTriggerClassName = this.activeTriggerClassNameMap[this.trigger]; | ||
// | ||
this.extraTriggerClassName = this.extraTriggerClassNameMap[this.trigger]; | ||
this.extraActiveTriggerClassName = this.extraActiveTriggerClassNameMap[this.trigger]; | ||
}, | ||
function getWordPosition(position, diff) { | ||
const prevText = textContent[position - 1]; | ||
if (prevText === null || prevText === undefined) { | ||
return position; | ||
} else if (prevText.trim().length === 0 || position <= 0 || textContent.length < position) { | ||
return position; | ||
} else { | ||
return getWordPosition(position + diff, diff); | ||
} | ||
} | ||
showPanel () { | ||
if (!this.mentionPanel.classList.contains(`medium-editor-mention-panel-active`)) { | ||
this.activatePanel(); | ||
this.wrapWordInMentionAt(); | ||
} | ||
this.positionPanel(); | ||
this.updatePanelContent(); | ||
}, | ||
this.wordStart = getWordPosition(startOffset + initialDiff, -1); | ||
this.wordEnd = getWordPosition(startOffset + initialDiff, 1) - 1; | ||
this.word = textContent.slice(this.wordStart, this.wordEnd); | ||
this.trigger = this.word.slice(0, 1); | ||
this.triggerClassName = this.triggerClassNameMap[this.trigger]; | ||
this.activeTriggerClassName = this.activeTriggerClassNameMap[this.trigger]; | ||
// | ||
this.extraTriggerClassName = this.extraTriggerClassNameMap[this.trigger]; | ||
this.extraActiveTriggerClassName = this.extraActiveTriggerClassNameMap[this.trigger]; | ||
}, | ||
activatePanel () { | ||
this.mentionPanel.classList.add(`medium-editor-mention-panel-active`); | ||
if (this.extraActivePanelClassName || this.extraActiveClassName) { | ||
this.mentionPanel.classList.add(this.extraActivePanelClassName || this.extraActiveClassName); | ||
} | ||
}, | ||
showPanel() { | ||
if (!this.mentionPanel.classList.contains(`medium-editor-mention-panel-active`)) { | ||
this.activatePanel(); | ||
this.wrapWordInMentionAt(); | ||
} | ||
this.positionPanel(); | ||
this.updatePanelContent(); | ||
}, | ||
wrapWordInMentionAt () { | ||
const selection = this.document.getSelection(); | ||
if (!selection.rangeCount) { | ||
return; | ||
} | ||
// http://stackoverflow.com/a/6328906/1458162 | ||
const range = selection.getRangeAt(0).cloneRange(); | ||
if (range.startContainer.parentNode.classList.contains(this.triggerClassName)) { | ||
this.activeMentionAt = range.startContainer.parentNode; | ||
} else { | ||
range.setStart(range.startContainer, this.wordStart); | ||
range.setEnd(range.startContainer, Math.min(this.wordEnd, range.startContainer.textContent.length)); | ||
// Instead, insert our own version of it. | ||
// TODO: Not sure why, but using <span> tag doens't work here | ||
const element = this.document.createElement(this.tagName); | ||
element.classList.add(this.triggerClassName); | ||
if (this.extraTriggerClassName) { | ||
element.classList.add(this.extraTriggerClassName); | ||
} | ||
this.activeMentionAt = element; | ||
// | ||
range.surroundContents(element); | ||
selection.removeAllRanges(); | ||
selection.addRange(range); | ||
// | ||
MediumEditor.selection.select(this.document, this.activeMentionAt.firstChild, this.word.length); | ||
} | ||
this.activeMentionAt.classList.add(this.activeTriggerClassName); | ||
if (this.extraActiveTriggerClassName) { | ||
this.activeMentionAt.classList.add(this.extraActiveTriggerClassName); | ||
} | ||
}, | ||
activatePanel() { | ||
this.mentionPanel.classList.add(`medium-editor-mention-panel-active`); | ||
if (this.extraActivePanelClassName || this.extraActiveClassName) { | ||
this.mentionPanel.classList.add(this.extraActivePanelClassName || this.extraActiveClassName); | ||
} | ||
}, | ||
positionPanel () { | ||
const {bottom, left, width} = this.activeMentionAt.getBoundingClientRect(); | ||
const {pageXOffset, pageYOffset} = this.window; | ||
wrapWordInMentionAt() { | ||
const selection = this.document.getSelection(); | ||
if (!selection.rangeCount) { | ||
return; | ||
} | ||
// http://stackoverflow.com/a/6328906/1458162 | ||
const range = selection.getRangeAt(0).cloneRange(); | ||
if (range.startContainer.parentNode.classList.contains(this.triggerClassName)) { | ||
this.activeMentionAt = range.startContainer.parentNode; | ||
} else { | ||
const nextWordEnd = Math.min(this.wordEnd, range.startContainer.textContent.length); | ||
range.setStart(range.startContainer, this.wordStart); | ||
range.setEnd(range.startContainer, nextWordEnd); | ||
// Instead, insert our own version of it. | ||
// TODO: Not sure why, but using <span> tag doens't work here | ||
const element = this.document.createElement(this.tagName); | ||
element.classList.add(this.triggerClassName); | ||
if (this.extraTriggerClassName) { | ||
element.classList.add(this.extraTriggerClassName); | ||
} | ||
this.activeMentionAt = element; | ||
// | ||
range.surroundContents(element); | ||
selection.removeAllRanges(); | ||
selection.addRange(range); | ||
// | ||
MediumEditor.selection.select( | ||
this.document, | ||
this.activeMentionAt.firstChild, | ||
this.word.length | ||
); | ||
} | ||
this.activeMentionAt.classList.add(this.activeTriggerClassName); | ||
if (this.extraActiveTriggerClassName) { | ||
this.activeMentionAt.classList.add(this.extraActiveTriggerClassName); | ||
} | ||
}, | ||
this.mentionPanel.style.top = `${ pageYOffset + bottom }px`; | ||
this.mentionPanel.style.left = `${ pageXOffset + left + width }px`; | ||
}, | ||
positionPanel() { | ||
const { bottom, left, width } = this.activeMentionAt.getBoundingClientRect(); | ||
const { pageXOffset, pageYOffset } = this.window; | ||
updatePanelContent () { | ||
this.renderPanelContent(this.mentionPanel, this.word, ::this.handleSelectMention); | ||
}, | ||
this.mentionPanel.style.top = `${ pageYOffset + bottom }px`; | ||
this.mentionPanel.style.left = `${ pageXOffset + left + width }px`; | ||
}, | ||
handleSelectMention (seletedText) { | ||
if (seletedText) { | ||
const textNode = this.activeMentionAt.firstChild; | ||
textNode.textContent = seletedText; | ||
MediumEditor.selection.select(this.document, textNode, seletedText.length); | ||
// | ||
this.hidePanel(false); | ||
} else { | ||
this.hidePanel(false); | ||
} | ||
}, | ||
updatePanelContent() { | ||
this.renderPanelContent(this.mentionPanel, this.word, ::this.handleSelectMention); | ||
}, | ||
handleSelectMention(seletedText) { | ||
if (seletedText) { | ||
const textNode = this.activeMentionAt.firstChild; | ||
textNode.textContent = seletedText; | ||
MediumEditor.selection.select(this.document, textNode, seletedText.length); | ||
// | ||
this.hidePanel(false); | ||
} else { | ||
this.hidePanel(false); | ||
} | ||
}, | ||
}); | ||
export default TCMention; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
14
674
84986
29
1