code snippets
parent
1f47a4b9b1
commit
1a15ab955e
|
@ -6,7 +6,7 @@ var MentionExtension = MediumEditor.Extension.extend({
|
|||
this.subscribe('blur', this.cancel.bind(this));
|
||||
},
|
||||
isEditMode: function() {
|
||||
return !this.base.origElements.parentNode.classList.contains('read-mode')
|
||||
return !this.base.origElements.parentNode.classList.contains('read-mode');
|
||||
},
|
||||
cancel: function() {
|
||||
if (this.isEditMode()) {
|
||||
|
@ -248,7 +248,7 @@ var MentionExtension = MediumEditor.Extension.extend({
|
|||
li.innerText = '@' + it.username;
|
||||
}
|
||||
|
||||
li.addEventListener('click', this.selectMention.bind(this, it));
|
||||
li.addEventListener('mousedown', this.selectMention.bind(this, it));
|
||||
|
||||
ul.appendChild(li);
|
||||
}.bind(this));
|
||||
|
|
|
@ -214,6 +214,9 @@
|
|||
}
|
||||
},
|
||||
"WYSIWYG": {
|
||||
"CODE_SNIPPET": "Code Snippet",
|
||||
"SELECT_LANGUAGE_PLACEHOLDER": "Select Language",
|
||||
"SELECT_LANGUAGE_REMOVE_FORMATING": "Remove formatting",
|
||||
"OUTDATED": "Another person has made changes while you were editing. Check the new version on the activiy tab before you save your changes.",
|
||||
"MARKDOWN_HELP": "Markdown syntax help"
|
||||
},
|
||||
|
|
|
@ -11,11 +11,12 @@
|
|||
span.detail-subject.e2e-title-subject(
|
||||
ng-if="!vm.permissions.canEdit"
|
||||
) {{vm.item.subject}}
|
||||
tg-svg.detail-edit.e2e-detail-edit(
|
||||
a(
|
||||
href=""
|
||||
ng-if="vm.permissions.canEdit"
|
||||
svg-icon="icon-edit"
|
||||
ng-click="vm.editSubject(true)"
|
||||
)
|
||||
tg-svg.detail-edit.e2e-detail-edit(svg-icon="icon-edit")
|
||||
|
||||
.edit-title-wrapper(ng-if="vm.editMode")
|
||||
input.edit-title-input.e2e-title-input(
|
||||
|
|
|
@ -23,17 +23,22 @@
|
|||
###
|
||||
|
||||
class WysiwygCodeHightlighterService
|
||||
constructor: () ->
|
||||
if !@.languages
|
||||
@.loadLanguages()
|
||||
|
||||
loadLanguages: () ->
|
||||
$.getJSON("/#{window._version}/prism/prism-languages.json").then (_languages_) =>
|
||||
getLanguages: () ->
|
||||
return new Promise (resolve, reject) =>
|
||||
if @.languages
|
||||
resolve(@.languages)
|
||||
else if @.loadPromise
|
||||
@.loadPromise.then () => resolve(@.languages)
|
||||
else
|
||||
@.loadPromise = $.getJSON("/#{window._version}/prism/prism-languages.json").then (_languages_) =>
|
||||
@.loadPromise = null
|
||||
@.languages = _.map _languages_, (it) ->
|
||||
it.url = "/#{window._version}/prism/" + it.file
|
||||
|
||||
return it
|
||||
|
||||
resolve(@.languages)
|
||||
|
||||
getLanguageInClassList: (classes) ->
|
||||
lan = _.find @.languages, (it) ->
|
||||
return !!_.find classes, (className) ->
|
||||
|
@ -41,123 +46,6 @@ class WysiwygCodeHightlighterService
|
|||
|
||||
return if lan then lan.name else null
|
||||
|
||||
addCodeLanguageSelectors: (mediumInstance) ->
|
||||
$(mediumInstance.elements[0]).find('code').each (index, code) =>
|
||||
if !code.classList.contains('has-code-lan-selector')
|
||||
code.classList.add('has-code-lan-selector') # prevent multi instanciate
|
||||
|
||||
currentLan = @.getLanguageInClassList(code.classList)
|
||||
code.parentNode.classList.add('language-' + currentLan)
|
||||
|
||||
id = new Date().getTime()
|
||||
|
||||
text = document.createTextNode(currentLan || 'text')
|
||||
|
||||
tab = document.createElement('div')
|
||||
tab.appendChild(text)
|
||||
tab.addEventListener 'click', () =>
|
||||
@.searchLanguage tab, (lan) =>
|
||||
if lan
|
||||
tab.innerText = lan
|
||||
@.updatePositionCodeTab(code.parentElement, tab)
|
||||
|
||||
languageClass = _.find code.classList, (className) ->
|
||||
return className && className.indexOf('language-') != -1
|
||||
|
||||
if languageClass
|
||||
code.classList.remove(languageClass.replace('language-', ''))
|
||||
code.classList.remove(languageClass)
|
||||
|
||||
code.classList.add('language-' + lan)
|
||||
code.classList.add(lan)
|
||||
|
||||
document.body.appendChild(tab)
|
||||
|
||||
code.dataset.tab = tab
|
||||
|
||||
if !code.dataset.tabId
|
||||
code.dataset.tabId = id
|
||||
code.classList.add(id)
|
||||
|
||||
tab.dataset.tabId = code.dataset.tabId
|
||||
|
||||
tab.classList.add('code-language-selector') # styles
|
||||
tab.classList.add('medium-' + mediumInstance.id) # used to delete
|
||||
|
||||
@.updatePositionCodeTab(code.parentElement, tab)
|
||||
|
||||
removeCodeLanguageSelectors: (mediumInstance) ->
|
||||
return if !mediumInstance || !mediumInstance.elements
|
||||
|
||||
$(mediumInstance.elements[0]).find('code').each (index, code) ->
|
||||
$(code).removeClass('has-code-lan-selector')
|
||||
|
||||
$('.medium-' + mediumInstance.id).remove()
|
||||
|
||||
updatePositionCodeTab: (node, tab) ->
|
||||
preRects = node.getBoundingClientRect()
|
||||
|
||||
tab.style.top = (preRects.top + $(window).scrollTop()) + 'px'
|
||||
tab.style.left = (preRects.left + preRects.width - tab.offsetWidth) + 'px'
|
||||
|
||||
getCodeLanHTML: (filter = '') ->
|
||||
template = _.template("""
|
||||
<% _.forEach(lans, function(lan) { %>
|
||||
<li><%- lan %></li><% });
|
||||
%>
|
||||
""");
|
||||
|
||||
filteresLans = _.map @.languages, (it) -> it.name
|
||||
|
||||
if filter.length
|
||||
filteresLans = _.filter filteresLans, (it) ->
|
||||
return it.indexOf(filter) != -1
|
||||
|
||||
return template({ 'lans': filteresLans });
|
||||
|
||||
searchLanguage: (tab, cb) ->
|
||||
search = document.createElement('div')
|
||||
|
||||
search.className = 'code-language-search'
|
||||
|
||||
preRects = tab.getBoundingClientRect()
|
||||
search.style.top = (preRects.top + $(window).scrollTop() + preRects.height) + 'px'
|
||||
search.style.left = preRects.left + 'px'
|
||||
|
||||
input = document.createElement('input')
|
||||
input.setAttribute('type', 'text')
|
||||
|
||||
ul = document.createElement('ul')
|
||||
|
||||
ul.innerHTML = @.getCodeLanHTML()
|
||||
|
||||
search.appendChild(input)
|
||||
search.appendChild(ul)
|
||||
|
||||
document.body.appendChild(search)
|
||||
|
||||
input.focus()
|
||||
|
||||
close = () ->
|
||||
search.remove()
|
||||
$(document.body).off('.leave-search-codelan')
|
||||
|
||||
clickedInSearchBox = (target) ->
|
||||
return $(search).is(target) || !!$(search).has(target).length
|
||||
|
||||
$(document.body).on 'mouseup.leave-search-codelan', (e) ->
|
||||
if !clickedInSearchBox(e.target)
|
||||
cb(null)
|
||||
close()
|
||||
|
||||
$(input).on 'keyup', (e) =>
|
||||
filter = e.currentTarget.value
|
||||
ul.innerHTML = @.getCodeLanHTML(filter)
|
||||
|
||||
$(ul).on 'click', 'li', (e) ->
|
||||
cb(e.currentTarget.innerText)
|
||||
close()
|
||||
|
||||
loadLanguage: (lan) ->
|
||||
return new Promise (resolve) ->
|
||||
if !Prism.languages[lan]
|
||||
|
@ -165,20 +53,11 @@ class WysiwygCodeHightlighterService
|
|||
else
|
||||
resolve()
|
||||
|
||||
removeHightlighter: (element) ->
|
||||
codes = $(element).find('code')
|
||||
|
||||
codes.each (index, code) ->
|
||||
code.innerHTML = code.innerText
|
||||
|
||||
# firefox adds br instead of new lines inside <code>
|
||||
replaceCodeBrToNl: (code) ->
|
||||
$(code).find('br').replaceWith('\n')
|
||||
|
||||
addHightlighter: (element) ->
|
||||
codes = $(element).find('code')
|
||||
|
||||
codes.each (index, code) =>
|
||||
hightlightCode: (code) ->
|
||||
@.replaceCodeBrToNl(code)
|
||||
|
||||
lan = @.getLanguageInClassList(code.classList)
|
||||
|
@ -186,14 +65,10 @@ class WysiwygCodeHightlighterService
|
|||
if lan
|
||||
@.loadLanguage(lan).then () -> Prism.highlightElement(code)
|
||||
|
||||
updateCodeLanguageSelector: (mediumInstance) ->
|
||||
$('.medium-' + mediumInstance.id).each (index, tab) =>
|
||||
node = $('.' + tab.dataset.tabId)
|
||||
addHightlighter: (element) ->
|
||||
codes = $(element).find('code')
|
||||
|
||||
if !node.length
|
||||
tab.remove()
|
||||
else
|
||||
@.updatePositionCodeTab(node.parent()[0], tab)
|
||||
codes.each (index, code) => @.hightlightCode(code)
|
||||
|
||||
angular.module("taigaComponents")
|
||||
.service("tgWysiwygCodeHightlighterService", WysiwygCodeHightlighterService)
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
###
|
||||
# Copyright (C) 2014-2017 Andrey Antukh <niwi@niwi.nz>
|
||||
# Copyright (C) 2014-2017 Jesús Espino Garcia <jespinog@gmail.com>
|
||||
# Copyright (C) 2014-2017 David Barragán Merino <bameda@dbarragan.com>
|
||||
# Copyright (C) 2014-2017 Alejandro Alonso <alejandro.alonso@kaleidos.net>
|
||||
# Copyright (C) 2014-2017 Juan Francisco Alcántara <juanfran.alcantara@kaleidos.net>
|
||||
# Copyright (C) 2014-2017 Xavi Julian <xavier.julian@kaleidos.net>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# File: modules/components/wysiwyg/wysiwyg-code-lightbox/wysiwyg-code-lightbox.directive.coffee
|
||||
###
|
||||
|
||||
WysiwygCodeLightbox = (lightboxService) ->
|
||||
link = (scope, el, attrs, ctrl) ->
|
||||
scope.$watch 'visible', (visible) ->
|
||||
if visible && !el.hasClass('open')
|
||||
scope.open = true
|
||||
lightboxService.open(el, null, scope.onClose)
|
||||
|
||||
scope.$applyAsync () ->
|
||||
textarea = el[0].querySelector('textarea')
|
||||
if textarea
|
||||
textarea.select()
|
||||
|
||||
else if !visible && el.hasClass('open')
|
||||
scope.open = false
|
||||
lightboxService.close(el)
|
||||
|
||||
return {
|
||||
scope: {
|
||||
languages: '<',
|
||||
codeLanguage: '<',
|
||||
code: '<',
|
||||
visible: '<',
|
||||
onClose: '&',
|
||||
onSave: '&'
|
||||
},
|
||||
link: link,
|
||||
templateUrl: "components/wysiwyg/wysiwyg-code-lightbox/wysiwyg-code-lightbox.html"
|
||||
}
|
||||
|
||||
angular.module("taigaComponents")
|
||||
.directive("tgWysiwygCodeLightbox", ["lightboxService", WysiwygCodeLightbox])
|
|
@ -0,0 +1,25 @@
|
|||
tg-lightbox-close(on-close="onClose()")
|
||||
|
||||
form(
|
||||
ng-if="open"
|
||||
ng-submit="onSave({lan: codeLanguage, code: code})"
|
||||
)
|
||||
h2.title(translate="COMMON.WYSIWYG.CODE_SNIPPET")
|
||||
|
||||
fieldset
|
||||
select(ng-model="codeLanguage")
|
||||
option(value="") {{'COMMON.WYSIWYG.SELECT_LANGUAGE_PLACEHOLDER' | translate}}
|
||||
option(value="remove-formating") {{'COMMON.WYSIWYG.SELECT_LANGUAGE_REMOVE_FORMATING' | translate}}
|
||||
option(
|
||||
ng-repeat="option in languages"
|
||||
ng-value="option.name"
|
||||
) {{option.name}}
|
||||
|
||||
fieldset
|
||||
textarea(ng-model="code")
|
||||
|
||||
fieldset
|
||||
button.button-green.submit-button(
|
||||
type="submit"
|
||||
translate="COMMON.SAVE"
|
||||
)
|
|
@ -0,0 +1,3 @@
|
|||
tg-wysiwyg-code-lightbox textarea {
|
||||
height: 350px;
|
||||
}
|
|
@ -26,36 +26,78 @@ taiga = @.taiga
|
|||
bindOnce = @.taiga.bindOnce
|
||||
|
||||
Medium = ($translate, $confirm, $storage, wysiwygService, animationFrame, tgLoader, wysiwygCodeHightlighterService, wysiwygMentionService, analytics) ->
|
||||
removeSelections = () ->
|
||||
if window.getSelection
|
||||
if window.getSelection().empty
|
||||
window.getSelection().empty();
|
||||
else if window.getSelection().removeAllRanges
|
||||
window.getSelection().removeAllRanges()
|
||||
|
||||
isCodeBlockSelected = (range, elm) ->
|
||||
return !!$(range.endContainer).parentsUntil('.editor', 'code').length
|
||||
else if document.selection
|
||||
document.selection.empty()
|
||||
|
||||
refreshCodeBlockHightlight = (elm) ->
|
||||
wysiwygCodeHightlighterService.refreshCodeLanguageSelectors(elm)
|
||||
getRangeCodeBlock = (range) ->
|
||||
return $(range.endContainer).parentsUntil('.editor', 'code')
|
||||
|
||||
isCodeBlockSelected = (range) ->
|
||||
return !!getRangeCodeBlock(range).length
|
||||
|
||||
removeCodeBlockAndHightlight = (selection, mediumInstance) ->
|
||||
if $(selection).is('code')
|
||||
code = selection
|
||||
else
|
||||
code = $(selection).closest('code')[0]
|
||||
|
||||
removeCodeBlockAndHightlight = (range, elm) ->
|
||||
code = $(range.endContainer).closest('code')[0]
|
||||
pre = code.parentNode
|
||||
|
||||
p = document.createElement('p')
|
||||
p.innerText = code.innerText
|
||||
|
||||
pre.parentNode.replaceChild(p, pre)
|
||||
|
||||
wysiwygCodeHightlighterService.removeCodeLanguageSelectors(elm)
|
||||
mediumInstance.checkContentChanged(mediumInstance.elements[0])
|
||||
|
||||
addCodeBlockAndHightlight = (range, elm) ->
|
||||
pre = document.createElement('pre')
|
||||
code = document.createElement('code')
|
||||
|
||||
pre.appendChild(code)
|
||||
console.log range.startContainer.parentNode.nextSibling
|
||||
|
||||
if !range.startContainer.parentNode.nextSibling
|
||||
$('<br/>').insertAfter(range.startContainer.parentNode)
|
||||
|
||||
start = range.startContainer.parentNode.nextSibling
|
||||
|
||||
code.appendChild(range.extractContents())
|
||||
range.insertNode(pre)
|
||||
|
||||
elm.checkContentChanged()
|
||||
pre.appendChild(code)
|
||||
|
||||
wysiwygCodeHightlighterService.addCodeLanguageSelectors(elm)
|
||||
start.parentNode.insertBefore(pre, start)
|
||||
|
||||
refreshCodeBlocks(elm)
|
||||
|
||||
refreshCodeBlocks = (mediumInstance) ->
|
||||
# clean empty <p> content editable adds it when range.extractContents has been execute it
|
||||
for mainChildren in mediumInstance.elements[0].children
|
||||
if mainChildren && mainChildren.tagName.toLowerCase() == 'p' && !mainChildren.innerText.length
|
||||
mainChildren.parentNode.removeChild(mainChildren)
|
||||
|
||||
preList = mediumInstance.elements[0].querySelectorAll('pre')
|
||||
|
||||
for pre in preList
|
||||
# prevent edit a pre
|
||||
pre.setAttribute('contenteditable', false)
|
||||
|
||||
if pre.nextElementSibling && pre.nextElementSibling.nodeName.toLowerCase() == 'p' && !pre.nextElementSibling.children.length
|
||||
pre.nextElementSibling.appendChild(document.createElement('br'))
|
||||
|
||||
# add p after every pre
|
||||
else if !pre.nextElementSibling || pre.nextElementSibling.nodeName.toLowerCase() != 'p'
|
||||
p = document.createElement('p')
|
||||
p.appendChild(document.createElement('br'))
|
||||
|
||||
pre.parentNode.insertBefore(p, pre.nextSibling)
|
||||
|
||||
mediumInstance.checkContentChanged(mediumInstance.elements[0])
|
||||
|
||||
AlignRightButton = MediumEditor.extensions.button.extend({
|
||||
name: 'rtl',
|
||||
|
@ -107,9 +149,16 @@ Medium = ($translate, $confirm, $storage, wysiwygService, animationFrame, tgLoad
|
|||
range = MediumEditor.selection.getSelectionRange(self.document)
|
||||
|
||||
if isCodeBlockSelected(range, this.base)
|
||||
removeCodeBlockAndHightlight(range, this.base)
|
||||
removeCodeBlockAndHightlight(range.endContainer, this.base)
|
||||
else
|
||||
addCodeBlockAndHightlight(range, this.base)
|
||||
removeSelections()
|
||||
|
||||
toolbar = this.base.getExtensionByName('toolbar')
|
||||
|
||||
if toolbar
|
||||
toolbar.hideToolbar()
|
||||
|
||||
})
|
||||
|
||||
CustomPasteHandler = MediumEditor.extensions.paste.extend({
|
||||
|
@ -141,6 +190,7 @@ Medium = ($translate, $confirm, $storage, wysiwygService, animationFrame, tgLoad
|
|||
mediumInstance = null
|
||||
editorMedium = $el.find('.medium')
|
||||
editorMarkdown = $el.find('.markdown')
|
||||
codeBlockSelected = null
|
||||
|
||||
isEditOnly = !!$attrs.$attr.editonly
|
||||
notPersist = !!$attrs.$attr.notPersist
|
||||
|
@ -149,12 +199,47 @@ Medium = ($translate, $confirm, $storage, wysiwygService, animationFrame, tgLoad
|
|||
$scope.editMode = isEditOnly || false
|
||||
$scope.mode = $storage.get('editor-mode', 'html')
|
||||
$scope.markdown = ''
|
||||
$scope.codeEditorVisible = false
|
||||
$scope.codeLans = []
|
||||
|
||||
wysiwygService.loadEmojis()
|
||||
|
||||
wysiwygCodeHightlighterService.getLanguages().then (codeLans) ->
|
||||
$scope.codeLans = codeLans
|
||||
|
||||
setHtmlMedium = (markdown) ->
|
||||
html = wysiwygService.getHTML(markdown)
|
||||
editorMedium.html(html)
|
||||
wysiwygCodeHightlighterService.addHightlighter(mediumInstance.elements[0])
|
||||
refreshCodeBlocks(mediumInstance)
|
||||
|
||||
$scope.saveSnippet = (lan, code) ->
|
||||
$scope.codeEditorVisible = false
|
||||
codeBlockSelected.innerText = code
|
||||
codePre = codeBlockSelected.parentNode
|
||||
|
||||
if lan == 'remove-formating'
|
||||
codeBlockSelected.className = ''
|
||||
codePre.className = ''
|
||||
|
||||
removeCodeBlockAndHightlight(codeBlockSelected, mediumInstance)
|
||||
else if _.trim(code).length
|
||||
if lan
|
||||
codeBlockSelected.className = 'language-' + lan
|
||||
codePre.className = 'language-' + lan
|
||||
else
|
||||
codeBlockSelected.className = ''
|
||||
codePre.className = ''
|
||||
|
||||
wysiwygCodeHightlighterService.hightlightCode(codeBlockSelected)
|
||||
mediumInstance.checkContentChanged(mediumInstance.elements[0])
|
||||
else
|
||||
codeBlockSelected.parentNode.parentNode.removeChild(codeBlockSelected.parentNode)
|
||||
mediumInstance.checkContentChanged(mediumInstance.elements[0])
|
||||
|
||||
throttleChange()
|
||||
|
||||
return null
|
||||
|
||||
$scope.setMode = (mode) ->
|
||||
$storage.set('editor-mode', mode)
|
||||
|
@ -191,7 +276,7 @@ Medium = ($translate, $confirm, $storage, wysiwygService, animationFrame, tgLoad
|
|||
if notPersist
|
||||
clean()
|
||||
else if $scope.mode == 'html'
|
||||
setHtmlMedium($scope.content)
|
||||
setHtmlMedium($scope.content || null)
|
||||
|
||||
$scope.markdown = $scope.content
|
||||
|
||||
|
@ -207,19 +292,6 @@ Medium = ($translate, $confirm, $storage, wysiwygService, animationFrame, tgLoad
|
|||
$scope.markdown = ''
|
||||
editorMedium.html('')
|
||||
|
||||
refreshExtras = () ->
|
||||
animationFrame.add () ->
|
||||
if $scope.mode == 'html'
|
||||
if $scope.editMode
|
||||
wysiwygCodeHightlighterService.addCodeLanguageSelectors(mediumInstance)
|
||||
wysiwygCodeHightlighterService.removeHightlighter(mediumInstance.elements[0])
|
||||
else
|
||||
wysiwygCodeHightlighterService.addHightlighter(mediumInstance.elements[0])
|
||||
wysiwygCodeHightlighterService.removeCodeLanguageSelectors(mediumInstance)
|
||||
else
|
||||
wysiwygCodeHightlighterService.removeHightlighter(mediumInstance.elements[0])
|
||||
wysiwygCodeHightlighterService.removeCodeLanguageSelectors(mediumInstance)
|
||||
|
||||
saveEnd = () ->
|
||||
$scope.saving = false
|
||||
|
||||
|
@ -305,7 +377,6 @@ Medium = ($translate, $confirm, $storage, wysiwygService, animationFrame, tgLoad
|
|||
change = () ->
|
||||
if $scope.mode == 'html'
|
||||
updateMarkdownWithCurrentHtml()
|
||||
wysiwygCodeHightlighterService.updateCodeLanguageSelector(mediumInstance)
|
||||
|
||||
localSave($scope.markdown)
|
||||
|
||||
|
@ -415,24 +486,6 @@ Medium = ($translate, $confirm, $storage, wysiwygService, animationFrame, tgLoad
|
|||
mediumInstance.subscribe 'editableDrop', (event) ->
|
||||
$scope.onUploadFile({files: event.dataTransfer.files, cb: uploadEnd})
|
||||
|
||||
editorMedium.on 'keydown', (e) ->
|
||||
code = if e.keyCode then e.keyCode else e.which
|
||||
range = MediumEditor.selection.getSelectionRange(document)
|
||||
codeBlock = isCodeBlockSelected(range, document)
|
||||
selection = window.getSelection()
|
||||
|
||||
if code == 13 && !e.shiftKey && selection.focusOffset == _.trimEnd(selection.focusNode.textContent).length
|
||||
e.preventDefault()
|
||||
document.execCommand('insertHTML', false, '<p id="last-p"><br/></p>')
|
||||
|
||||
lastP = $('#last-p').attr('id', '')
|
||||
|
||||
range = document.createRange()
|
||||
range.selectNodeContents(lastP[0])
|
||||
range.collapse(true);
|
||||
|
||||
MediumEditor.selection.selectRange(document, range)
|
||||
|
||||
mediumInstance.subscribe 'editableKeydown', (e) ->
|
||||
code = if e.keyCode then e.keyCode else e.which
|
||||
|
||||
|
@ -452,12 +505,18 @@ Medium = ($translate, $confirm, $storage, wysiwygService, animationFrame, tgLoad
|
|||
|
||||
$scope.editMode = editMode
|
||||
|
||||
$scope.$applyAsync(refreshExtras)
|
||||
$scope.$applyAsync () ->
|
||||
wysiwygCodeHightlighterService.addHightlighter(mediumInstance.elements[0])
|
||||
refreshCodeBlocks(mediumInstance)
|
||||
|
||||
$scope.$watch () ->
|
||||
return $scope.mode + ":" + $scope.editMode
|
||||
, () ->
|
||||
$scope.$applyAsync(refreshExtras)
|
||||
$(editorMedium[0]).on 'dblclick', 'pre', (e) ->
|
||||
$scope.$applyAsync () ->
|
||||
$scope.codeEditorVisible = true
|
||||
|
||||
codeBlockSelected = e.currentTarget.querySelector('code')
|
||||
|
||||
$scope.currentCodeLanguage = wysiwygCodeHightlighterService.getLanguageInClassList(codeBlockSelected.classList)
|
||||
$scope.code = codeBlockSelected.innerText
|
||||
|
||||
unwatch = $scope.$watch 'content', (content) ->
|
||||
if !_.isUndefined(content)
|
||||
|
@ -466,7 +525,7 @@ Medium = ($translate, $confirm, $storage, wysiwygService, animationFrame, tgLoad
|
|||
if !mediumInstance && isDraft()
|
||||
$scope.editMode = true
|
||||
|
||||
if $scope.markdown == content
|
||||
if ($scope.markdown.length || content.length) && $scope.markdown == content
|
||||
return
|
||||
|
||||
content = getCurrentContent()
|
||||
|
@ -487,7 +546,6 @@ Medium = ($translate, $confirm, $storage, wysiwygService, animationFrame, tgLoad
|
|||
|
||||
$scope.$on "$destroy", () ->
|
||||
if mediumInstance
|
||||
wysiwygCodeHightlighterService.removeCodeLanguageSelectors(mediumInstance)
|
||||
mediumInstance.destroy()
|
||||
|
||||
return {
|
||||
|
|
|
@ -90,12 +90,12 @@
|
|||
}
|
||||
pre:not([class*="language-"]) {
|
||||
@include font-size(small);
|
||||
background: lighten($grayer, 10%);
|
||||
background: $code-bg;
|
||||
color: $whitish;
|
||||
direction: ltr;
|
||||
font-family: 'courier new', 'monospace';
|
||||
line-height: 1.4rem;
|
||||
margin-bottom: 1rem;
|
||||
margin-bottom: .5rem;
|
||||
overflow: auto;
|
||||
padding: 1rem;
|
||||
unicode-bidi: embed;
|
||||
|
@ -165,6 +165,12 @@
|
|||
tg-wysiwyg {
|
||||
display: flex;
|
||||
margin-bottom: 2rem;
|
||||
div[contenteditable="true"] *:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
pre {
|
||||
cursor: pointer;
|
||||
}
|
||||
.outdated {
|
||||
color: $red;
|
||||
}
|
||||
|
@ -191,6 +197,7 @@ tg-wysiwyg {
|
|||
.medium-editor-placeholder,
|
||||
.markdown-editor-placeholder {
|
||||
color: $gray-light;
|
||||
overflow: visible;
|
||||
padding-left: 1rem;
|
||||
&::after { // overwrite medium css
|
||||
color: $gray-light;
|
||||
|
|
|
@ -56,3 +56,12 @@
|
|||
title="{{ 'COMMON.CANCEL' | translate }}"
|
||||
)
|
||||
tg-svg(svg-icon="icon-close")
|
||||
|
||||
tg-wysiwyg-code-lightbox.lightbox.lightbox-generic-form(
|
||||
languages="codeLans"
|
||||
code-language="currentCodeLanguage"
|
||||
code="code"
|
||||
visible="codeEditorVisible"
|
||||
on-close="codeEditorVisible = false"
|
||||
on-save="saveSnippet(lan, code)"
|
||||
)
|
|
@ -59,7 +59,7 @@
|
|||
.no-description {
|
||||
color: $gray-light;
|
||||
}
|
||||
textarea {
|
||||
.markdown {
|
||||
background: $white;
|
||||
height: 10rem;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ $tribe-secondary: darken($tribe-primary, 10%);
|
|||
|
||||
$top-icon-color: $white;
|
||||
$dropdown-color: rgba(darken($primary-dark, 20%), 1);
|
||||
$code-bg: #272822;
|
||||
|
||||
/* Overwrite mixins */
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ $tribe-secondary: darken($tribe-primary, 10%);
|
|||
|
||||
$top-icon-color: $white;
|
||||
$dropdown-color: rgba(darken($primary-dark, 20%), 1);
|
||||
$code-bg: #272822;
|
||||
|
||||
/* Overwrite mixins */
|
||||
|
||||
|
|
|
@ -39,3 +39,4 @@ $tribe-secondary: darken($tribe-primary, 10%);
|
|||
|
||||
$top-icon-color: #11241f;
|
||||
$dropdown-color: rgba(darken($grayer, 20%), 1);
|
||||
$code-bg: #272822;
|
|
@ -12,7 +12,12 @@ helper.title = function() {
|
|||
},
|
||||
|
||||
setTitle: function(title) {
|
||||
el.$('.e2e-detail-edit').click();
|
||||
browser
|
||||
.actions()
|
||||
.mouseMove(el.$('.e2e-detail-edit'))
|
||||
.click()
|
||||
.perform();
|
||||
|
||||
el.$('.e2e-title-input').clear().sendKeys(title);
|
||||
},
|
||||
|
||||
|
|
|
@ -14,9 +14,10 @@ var shared = module.exports;
|
|||
|
||||
function selectEditorFirstChild(elm) {
|
||||
browser.executeScript(function () {
|
||||
// select the first paragraph
|
||||
var range = document.createRange();
|
||||
range.selectNode(arguments[0].firstChild);
|
||||
|
||||
range.setStart(arguments[0].firstChild.firstChild, 0);
|
||||
range.setEnd(arguments[0].firstChild.firstChild, arguments[0].firstChild.innerText.length);
|
||||
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
|
@ -45,34 +46,76 @@ function getMarkdownTextarea(elm) {
|
|||
return elm.$('.e2e-markdown-textarea');}
|
||||
|
||||
|
||||
function htmlMode() {
|
||||
$('.e2e-html-mode').click();
|
||||
function htmlMode(elm) {
|
||||
elm.$('.e2e-html-mode').click();
|
||||
|
||||
return utils.common.waitElementPresent($('.e2e-markdown-mode'));
|
||||
}
|
||||
|
||||
function markdownMode() {
|
||||
$('.e2e-markdown-mode').click();
|
||||
function markdownMode(elm) {
|
||||
elm.$('.e2e-markdown-mode').click();
|
||||
|
||||
return utils.common.waitElementPresent($('.e2e-html-mode'));
|
||||
}
|
||||
|
||||
function saveEdition() {
|
||||
$('.e2e-save-editor').click();
|
||||
function saveEdition(elm) {
|
||||
return elm.$('.e2e-save-editor').click();
|
||||
}
|
||||
|
||||
function cancelEdition(elm) {
|
||||
$('.e2e-cancel-editor').click();
|
||||
elm.$('.e2e-cancel-editor').click();
|
||||
|
||||
return browser.wait(async () => {
|
||||
return !!await elm.$$('.read-mode').count();
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
function closeMention() {
|
||||
return utils.common.waitElementNotPresent($('.medium-mention'));
|
||||
}
|
||||
|
||||
function preventThrottle() {
|
||||
return browser.sleep(250);
|
||||
}
|
||||
|
||||
function getSnippeLightbox(parent) {
|
||||
let el = parent.$('tg-wysiwyg-code-lightbox');
|
||||
|
||||
let obj = {
|
||||
el: el,
|
||||
waitOpen: function() {
|
||||
return utils.lightbox.open(el);
|
||||
},
|
||||
waitClose: function() {
|
||||
return utils.lightbox.close(el);
|
||||
},
|
||||
select: function(lan) {
|
||||
return el.$('select').sendKeys('javascript');
|
||||
},
|
||||
save: function() {
|
||||
return el.$('button').click();
|
||||
}
|
||||
};
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
async function edit(elm, elmWrapper, text = null) {
|
||||
await browser.wait(EC.elementToBeClickable(elm), 10000);
|
||||
|
||||
elm.click();
|
||||
|
||||
browser.sleep(200);
|
||||
await browser.sleep(2000);
|
||||
|
||||
browser.executeScript(function () {
|
||||
if (text !== null) {
|
||||
await cleanWysiwyg(elm, elmWrapper);
|
||||
|
||||
return elm.sendKeys(text);
|
||||
}
|
||||
};
|
||||
|
||||
async function cleanWysiwyg(elm, elmWrapper) {
|
||||
await browser.executeScript(function () {
|
||||
if(arguments[0].firstChild) {
|
||||
var range = document.createRange();
|
||||
range.setStart(arguments[0].firstChild, 0);
|
||||
|
@ -84,26 +127,7 @@ async function edit(elm, elmWrapper, text = null) {
|
|||
}
|
||||
}, elm.getWebElement());
|
||||
|
||||
if (text !== null) {
|
||||
await cleanWysiwyg(elm, elmWrapper);
|
||||
|
||||
return elm.sendKeys(text);
|
||||
}
|
||||
}
|
||||
|
||||
async function cleanWysiwyg(elm, elmWrapper) {
|
||||
let isHtmlMode = await elm.isDisplayed();
|
||||
|
||||
if (isHtmlMode) {
|
||||
let isPresent = await $('.e2e-markdown-mode').isPresent();
|
||||
|
||||
markdownMode();
|
||||
}
|
||||
var markdownTextarea = getMarkdownTextarea(elmWrapper);
|
||||
|
||||
await utils.common.clear(markdownTextarea);
|
||||
|
||||
return htmlMode();
|
||||
return elm.sendKeys(protractor.Key.BACK_SPACE);
|
||||
}
|
||||
|
||||
shared.wysiwygTestingComments = function(parentSelector, section) {
|
||||
|
@ -126,15 +150,15 @@ shared.wysiwygTestingComments = function(parentSelector, section) {
|
|||
|
||||
resetSelection();
|
||||
|
||||
markdownMode();
|
||||
markdownMode(editorWrapper);
|
||||
|
||||
let markdown = await getMarkdownText(editorWrapper);
|
||||
|
||||
expect(markdown).to.be.equal('**test**');
|
||||
|
||||
htmlMode();
|
||||
await htmlMode(editorWrapper);
|
||||
|
||||
saveEdition();
|
||||
await saveEdition(editorWrapper);
|
||||
|
||||
let newCommentsCounter = await historyHelper.countComments();
|
||||
expect(newCommentsCounter).to.be.equal(commentsCounter+1);
|
||||
|
@ -145,50 +169,29 @@ shared.wysiwygTestingComments = function(parentSelector, section) {
|
|||
|
||||
await edit(editor, editorWrapper, '');
|
||||
|
||||
markdownMode();
|
||||
markdownMode(editorWrapper);
|
||||
|
||||
let markdownTextarea = getMarkdownTextarea(editorWrapper);
|
||||
|
||||
await markdownTextarea.sendKeys('_test2_');
|
||||
|
||||
htmlMode();
|
||||
await htmlMode(editorWrapper);
|
||||
|
||||
let html = await editor.getAttribute("innerHTML");
|
||||
|
||||
expect(html).to.be.eql('<p><em>test2</em></p>\n');
|
||||
|
||||
saveEdition();
|
||||
await saveEdition(editorWrapper);
|
||||
|
||||
let newCommentsCounter = await historyHelper.countComments();
|
||||
expect(newCommentsCounter).to.be.equal(commentsCounter+1);
|
||||
});
|
||||
|
||||
it('code block', async () => {
|
||||
await edit(editor, editorWrapper, '');
|
||||
|
||||
editor.sendKeys("var test = 2;");
|
||||
|
||||
selectEditorFirstChild(editor);
|
||||
|
||||
$('.medium-editor-toolbar-active .medium-editor-button-last').click();
|
||||
|
||||
$('.code-language-selector').click();
|
||||
$('.code-language-search input').sendKeys('javascript');
|
||||
$('.code-language-search li').click();
|
||||
|
||||
saveEdition();
|
||||
|
||||
let lastComment = historyHelper.getComments().last();
|
||||
|
||||
let hasHightlighter = !!await lastComment.$$('.token').count();
|
||||
|
||||
expect(hasHightlighter).to.be.true;
|
||||
});
|
||||
|
||||
it('confirm exit when there is changes', async () => {
|
||||
await edit(editor, editorWrapper, '');
|
||||
|
||||
editor.sendKeys('text text text');
|
||||
await preventThrottle();
|
||||
editor.sendKeys(protractor.Key.ESCAPE);
|
||||
|
||||
await utils.lightbox.confirm.ok();
|
||||
|
@ -206,6 +209,7 @@ shared.wysiwygTestingComments = function(parentSelector, section) {
|
|||
await edit(editor, editorWrapper, '');
|
||||
|
||||
editor.sendKeys('text text text');
|
||||
await preventThrottle();
|
||||
editor.sendKeys(protractor.Key.ESCAPE);
|
||||
|
||||
browser.sleep(400);
|
||||
|
@ -225,21 +229,21 @@ shared.wysiwygTestingComments = function(parentSelector, section) {
|
|||
it('mention user', async () => {
|
||||
await edit(editor, editorWrapper, '');
|
||||
|
||||
editor.sendKeys('@use');
|
||||
editor.sendKeys('@user8');
|
||||
|
||||
$$('.medium-mention li').get(2).click();
|
||||
$$('.medium-mention li').get(0).click();
|
||||
|
||||
let html = await editor.getAttribute("innerHTML");
|
||||
|
||||
expect(html).to.be.eql('<p><a href="/profile/user8">@user8</a> </p>');
|
||||
|
||||
markdownMode();
|
||||
markdownMode(editorWrapper);
|
||||
|
||||
let markdown = await getMarkdownText(editorWrapper);
|
||||
|
||||
expect(markdown).to.be.equal('[@user8](/profile/user8)');
|
||||
|
||||
htmlMode();
|
||||
await htmlMode(editorWrapper);
|
||||
|
||||
await cancelEdition(editorWrapper);
|
||||
});
|
||||
|
@ -255,13 +259,13 @@ shared.wysiwygTestingComments = function(parentSelector, section) {
|
|||
|
||||
expect(html).to.include('1f604.png');
|
||||
|
||||
markdownMode();
|
||||
markdownMode(editorWrapper);
|
||||
|
||||
let markdown = await getMarkdownText(editorWrapper);
|
||||
|
||||
expect(markdown).to.be.equal(':smile:');
|
||||
|
||||
htmlMode();
|
||||
await htmlMode(editorWrapper);
|
||||
|
||||
await cancelEdition(editorWrapper);
|
||||
});
|
||||
|
@ -287,7 +291,7 @@ shared.wysiwygTestingComments = function(parentSelector, section) {
|
|||
await edit(editLast, editWrapperLast, "This is the new and updated text");
|
||||
await utils.common.takeScreenshot(section, "edit comment");
|
||||
|
||||
saveEdition();
|
||||
await saveEdition(editWrapperLast);
|
||||
|
||||
//Show versions from last comment edited
|
||||
historyHelper.showVersionsLastComment();
|
||||
|
@ -318,6 +322,32 @@ shared.wysiwygTestingComments = function(parentSelector, section) {
|
|||
|
||||
await utils.common.takeScreenshot(section, 'restored comment');
|
||||
});
|
||||
|
||||
it('code block', async () => {
|
||||
await edit(editor, editorWrapper, '');
|
||||
|
||||
editor.sendKeys("var test = 2;");
|
||||
|
||||
selectEditorFirstChild(editor);
|
||||
|
||||
$('.medium-editor-toolbar-active .medium-editor-button-last').click();
|
||||
|
||||
browser.actions().doubleClick(editor.$('code')).perform();
|
||||
|
||||
let lb = getSnippeLightbox(editorWrapper);
|
||||
|
||||
await lb.waitOpen();
|
||||
|
||||
await lb.select('javascript');
|
||||
await lb.save();
|
||||
await lb.waitClose();
|
||||
|
||||
let hasHightlighter = !!await editor.$$('.token').count();
|
||||
|
||||
expect(hasHightlighter).to.be.true;
|
||||
|
||||
await saveEdition(editorWrapper);
|
||||
});
|
||||
};
|
||||
|
||||
shared.wysiwygTesting = function(parentSelector) {
|
||||
|
@ -331,9 +361,14 @@ shared.wysiwygTesting = function(parentSelector) {
|
|||
editor.click();
|
||||
}
|
||||
|
||||
let isHtmlMode = await editor.isDisplayed();
|
||||
if (!isHtmlMode) {
|
||||
await htmlMode(editorWrapper);
|
||||
}
|
||||
|
||||
await cleanWysiwyg(editor, editorWrapper);
|
||||
|
||||
markdownMode();
|
||||
markdownMode(editorWrapper);
|
||||
|
||||
var markdownTextarea = getMarkdownTextarea(editorWrapper);
|
||||
|
||||
|
@ -341,9 +376,9 @@ shared.wysiwygTesting = function(parentSelector) {
|
|||
|
||||
await markdownTextarea.sendKeys('test');
|
||||
|
||||
htmlMode();
|
||||
await htmlMode(editorWrapper);
|
||||
|
||||
saveEdition();
|
||||
await saveEdition(editorWrapper);
|
||||
|
||||
await browser.wait(EC.elementToBeClickable(editor), 10000);
|
||||
});
|
||||
|
@ -364,13 +399,13 @@ shared.wysiwygTesting = function(parentSelector) {
|
|||
|
||||
let html = await editor.getAttribute("innerHTML");
|
||||
|
||||
expect(html).to.be.eql('<p><b>test</b></p>');
|
||||
expect(html).to.be.eql('<p><b>test</b></p>\n');
|
||||
|
||||
saveEdition();
|
||||
await saveEdition(editorWrapper);
|
||||
|
||||
await edit(editor, editorWrapper);
|
||||
|
||||
markdownMode();
|
||||
markdownMode(editorWrapper);
|
||||
|
||||
let markdown = await getMarkdownText(editorWrapper);
|
||||
|
||||
|
@ -380,43 +415,24 @@ shared.wysiwygTesting = function(parentSelector) {
|
|||
it('convert to html', async () => {
|
||||
await edit(editor, editorWrapper, '');
|
||||
|
||||
markdownMode();
|
||||
markdownMode(editorWrapper);
|
||||
|
||||
let markdownTextarea = getMarkdownTextarea(editorWrapper);
|
||||
|
||||
await markdownTextarea.sendKeys('_test2_');
|
||||
|
||||
htmlMode();
|
||||
htmlMode(editorWrapper);
|
||||
|
||||
let html = await editor.getAttribute("innerHTML");
|
||||
|
||||
expect(html).to.be.eql('<p><em>test2</em></p>\n');
|
||||
});
|
||||
|
||||
it('code block', async () => {
|
||||
await edit(editor, editorWrapper, '');
|
||||
|
||||
editor.sendKeys("var test = 2;");
|
||||
|
||||
selectEditorFirstChild(editor);
|
||||
|
||||
$('.medium-editor-toolbar-active .medium-editor-button-last').click();
|
||||
|
||||
$('.code-language-selector').click();
|
||||
$('.code-language-search input').sendKeys('javascript');
|
||||
$('.code-language-search li').click();
|
||||
|
||||
saveEdition();
|
||||
|
||||
let hasHightlighter = !!await editor.$$('.token').count();
|
||||
|
||||
expect(hasHightlighter).to.be.true;
|
||||
});
|
||||
|
||||
it('save with confirmconfirm exit when there is changes', async () => {
|
||||
await edit(editor, editorWrapper, '');
|
||||
|
||||
editor.sendKeys('text text text');
|
||||
await preventThrottle();
|
||||
editor.sendKeys(protractor.Key.ESCAPE);
|
||||
|
||||
await utils.lightbox.confirm.ok();
|
||||
|
@ -434,6 +450,7 @@ shared.wysiwygTesting = function(parentSelector) {
|
|||
await edit(editor, editorWrapper, '');
|
||||
|
||||
editor.sendKeys('text text text');
|
||||
await preventThrottle();
|
||||
editor.sendKeys(protractor.Key.ESCAPE);
|
||||
|
||||
browser.sleep(400);
|
||||
|
@ -451,21 +468,24 @@ shared.wysiwygTesting = function(parentSelector) {
|
|||
it('mention user', async () => {
|
||||
await edit(editor, editorWrapper, '');
|
||||
|
||||
editor.sendKeys('@use');
|
||||
await editor.sendKeys('@user5');
|
||||
|
||||
$$('.medium-mention li').get(2).click();
|
||||
$$('.medium-mention li').get(0).click();
|
||||
|
||||
await closeMention();
|
||||
|
||||
let html = await editor.getAttribute("innerHTML");
|
||||
|
||||
expect(html).to.be.eql('<p><a href="/profile/user8">@user8</a> </p>');
|
||||
|
||||
markdownMode();
|
||||
expect(html).to.be.eql('<p><a href="/profile/user5">@user5</a> </p>\n');
|
||||
|
||||
markdownMode(editorWrapper);
|
||||
|
||||
let markdown = await getMarkdownText(editorWrapper);
|
||||
|
||||
expect(markdown).to.be.equal('[@user8](/profile/user8)');
|
||||
expect(markdown).to.be.equal('[@user5](/profile/user5)');
|
||||
|
||||
htmlMode();
|
||||
htmlMode(editorWrapper);
|
||||
});
|
||||
|
||||
it('emojis', async () => {
|
||||
|
@ -473,13 +493,15 @@ shared.wysiwygTesting = function(parentSelector) {
|
|||
|
||||
editor.sendKeys(':smil');
|
||||
|
||||
$$('.medium-mention li').get(2).click();
|
||||
await $$('.medium-mention li').get(2).click();
|
||||
|
||||
await closeMention();
|
||||
|
||||
let html = await editor.getAttribute("innerHTML");
|
||||
|
||||
expect(html).to.include('1f604.png');
|
||||
|
||||
markdownMode();
|
||||
markdownMode(editorWrapper);
|
||||
|
||||
let markdown = await getMarkdownText(editorWrapper);
|
||||
|
||||
|
@ -497,4 +519,30 @@ shared.wysiwygTesting = function(parentSelector) {
|
|||
|
||||
expect(html).to.be.equal(prevHtml);
|
||||
});
|
||||
|
||||
it('code block', async () => {
|
||||
await edit(editor, editorWrapper, '');
|
||||
|
||||
editor.sendKeys("var test = 2;");
|
||||
|
||||
selectEditorFirstChild(editor);
|
||||
|
||||
$('.medium-editor-toolbar-active .medium-editor-button-last').click();
|
||||
|
||||
browser.actions().doubleClick(editor.$('code')).perform();
|
||||
|
||||
let lb = getSnippeLightbox(editorWrapper);
|
||||
|
||||
await lb.waitOpen();
|
||||
|
||||
await lb.select('javascript');
|
||||
await lb.save();
|
||||
await lb.waitClose();
|
||||
|
||||
await saveEdition(editorWrapper);
|
||||
|
||||
let hasHightlighter = !!await editor.$$('.token').count();
|
||||
|
||||
expect(hasHightlighter).to.be.true;
|
||||
});
|
||||
};
|
||||
|
|
|
@ -476,7 +476,7 @@ describe('backlog', function() {
|
|||
|
||||
expect(sprintCount).is.below(newSprintCount);
|
||||
});
|
||||
it.only('hide forecasting if no velocity', async function() {
|
||||
it('hide forecasting if no velocity', async function() {
|
||||
browser.get(browser.params.glob.host + 'project/project-5/backlog');
|
||||
await utils.common.waitLoader();
|
||||
|
||||
|
|
|
@ -65,29 +65,7 @@ describe('wiki', function() {
|
|||
await utils.common.takeScreenshot("wiki", "deleting-the-created-link");
|
||||
});
|
||||
|
||||
describe('wiki editor', sharedWysiwyg.bind(this));
|
||||
|
||||
it('confirm close with ESC in lightbox', async function() {
|
||||
wikiHelper.editor().enabledEditionMode();
|
||||
|
||||
browser.actions().sendKeys(protractor.Key.ESCAPE).perform();
|
||||
|
||||
await utils.lightbox.confirm.cancel();
|
||||
|
||||
let descriptionVisibility = await $('.view-wiki-content').isDisplayed();
|
||||
|
||||
expect(descriptionVisibility).to.be.false;
|
||||
|
||||
wikiHelper.editor().focus();
|
||||
|
||||
browser.actions().sendKeys(protractor.Key.ESCAPE).perform();
|
||||
|
||||
await utils.lightbox.confirm.ok();
|
||||
|
||||
descriptionVisibility = await $('.view-wiki-content').isDisplayed();
|
||||
|
||||
expect(descriptionVisibility).to.be.true;
|
||||
});
|
||||
describe('wiki editor', sharedWysiwyg.bind(this, '.wiki'));
|
||||
|
||||
it('attachments', sharedDetail.attachmentTesting);
|
||||
|
||||
|
@ -96,28 +74,4 @@ describe('wiki', function() {
|
|||
|
||||
expect(browser.getCurrentUrl()).to.be.eventually.equal(browser.params.glob.host + 'project/project-0/wiki/home');
|
||||
});
|
||||
|
||||
it('Custom keyboard actions', async function(){
|
||||
wikiHelper.editor().enabledEditionMode();
|
||||
|
||||
wikiHelper.editor().setText("- aa");
|
||||
browser.actions().sendKeys(protractor.Key.ENTER).perform();
|
||||
let text = await wikiHelper.editor().getText();
|
||||
expect(text).to.be.equal("- aa\n- ");
|
||||
|
||||
wikiHelper.editor().setText("- ");
|
||||
browser.actions().sendKeys(protractor.Key.ENTER).perform();
|
||||
text = await wikiHelper.editor().getText();
|
||||
expect(text).to.be.equal("\n");
|
||||
|
||||
wikiHelper.editor().setText("- bbcc");
|
||||
browser.actions().sendKeys(protractor.Key.ARROW_LEFT).sendKeys(protractor.Key.ARROW_LEFT).sendKeys(protractor.Key.ENTER).perform();
|
||||
text = await wikiHelper.editor().getText();
|
||||
expect(text).to.be.equal("- bb\n- cc");
|
||||
|
||||
wikiHelper.editor().setText("- aa");
|
||||
browser.actions().sendKeys(protractor.Key.HOME).sendKeys(protractor.Key.ENTER).perform();
|
||||
text = await wikiHelper.editor().getText();
|
||||
expect(text).to.be.equal("\n- aa");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -20,6 +20,20 @@ common.getElm = function(el) {
|
|||
return deferred.promise;
|
||||
};
|
||||
|
||||
common.waitElementNotPresent = function(el) {
|
||||
return browser.wait(function() {
|
||||
return el.isPresent().then(function(present) {
|
||||
return !present;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
common.waitElementPresent = function(el) {
|
||||
return browser.wait(function() {
|
||||
return el.isPresent();
|
||||
});
|
||||
};
|
||||
|
||||
common.hasClass = async function (element, cls) {
|
||||
let classes = await element.getAttribute('class');
|
||||
|
||||
|
|
Loading…
Reference in New Issue