181 lines
6.2 KiB
CoffeeScript
181 lines
6.2 KiB
CoffeeScript
###
|
|
# Copyright (C) 2014-2016 Andrey Antukh <niwi@niwi.nz>
|
|
# Copyright (C) 2014-2016 Jesús Espino Garcia <jespinog@gmail.com>
|
|
# Copyright (C) 2014-2016 David Barragán Merino <bameda@dbarragan.com>
|
|
# Copyright (C) 2014-2016 Alejandro Alonso <alejandro.alonso@kaleidos.net>
|
|
# Copyright (C) 2014-2016 Juan Francisco Alcántara <juanfran.alcantara@kaleidos.net>
|
|
# Copyright (C) 2014-2016 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-hightlighter.service.coffee
|
|
###
|
|
|
|
class WysiwygCodeHightlighterService
|
|
constructor: () ->
|
|
if !@.languages
|
|
@.loadLanguages()
|
|
|
|
loadLanguages: () ->
|
|
$.getJSON("/#{window._version}/prism/prism-languages.json").then (_languages_) =>
|
|
@.languages = _.map _languages_, (it) ->
|
|
it.url = "/#{window._version}/prism/" + it.file
|
|
|
|
return it
|
|
|
|
getLanguageInClassList: (classes) ->
|
|
lan = _.find @.languages, (it) ->
|
|
return !!_.find classes, (className) ->
|
|
return 'language-' + it.name == className
|
|
|
|
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)
|
|
|
|
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)
|
|
code.classList.add('language-' + lan)
|
|
code.classList.add(lan)
|
|
|
|
document.body.appendChild(tab)
|
|
|
|
code.classList.add(id)
|
|
code.dataset.tab = tab
|
|
|
|
tab.classList.add('code-language-selector') # styles
|
|
tab.classList.add('medium-' + mediumInstance.id) # used to delete
|
|
tab.dataset.tabId = id
|
|
|
|
@.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]
|
|
ljs.load("/#{window._version}/prism/prism-#{lan}.min.js", resolve)
|
|
else
|
|
resolve()
|
|
|
|
removeHightlighter: (element) ->
|
|
codes = $(element).find('code')
|
|
|
|
codes.each (index, code) ->
|
|
code.innerHTML = code.innerText
|
|
|
|
addHightlighter: (element) ->
|
|
codes = $(element).find('code')
|
|
|
|
codes.each (index, code) =>
|
|
lan = @.getLanguageInClassList(code.classList)
|
|
|
|
if lan
|
|
@.loadLanguage(lan).then () -> Prism.highlightElement(code)
|
|
|
|
updateCodeLanguageSelector: (mediumInstance) ->
|
|
$('.medium-' + mediumInstance.id).each (index, tab) =>
|
|
node = $('.' + tab.dataset.tabId)
|
|
|
|
if !node.length
|
|
tab.remove()
|
|
else
|
|
@.updatePositionCodeTab(node.parent()[0], tab)
|
|
|
|
angular.module("taigaComponents")
|
|
.service("tgWysiwygCodeHightlighterService", WysiwygCodeHightlighterService)
|