The communications platform that puts data protection first.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
Rocket.Chat/packages/rocketchat-theme/server/server.coffee

159 lines
3.9 KiB

less = Npm.require('less')
autoprefixer = Npm.require('less-plugin-autoprefix')
crypto = Npm.require('crypto')
logger = new Logger 'rocketchat:theme',
methods:
stop_rendering:
type: 'info'
WebApp.rawConnectHandlers.use (req, res, next) ->
path = req.url.split("?")[0]
prefix = __meteor_runtime_config__.ROOT_URL_PATH_PREFIX || ''
if (path == "#{prefix}/__cordova/theme.css" || path == "#{prefix}/theme.css")
css = RocketChat.theme.getCss()
hash = crypto.createHash('sha1').update(css).digest('hex')
res.setHeader('Content-Type', 'text/css; charset=UTF-8')
res.setHeader('ETag', '"' + hash + '"')
res.write(css)
res.end()
else
next()
calculateClientHash = WebAppHashing.calculateClientHash
WebAppHashing.calculateClientHash = (manifest, includeFilter, runtimeConfigOverride) ->
css = RocketChat.theme.getCss()
if css.trim() isnt ''
hash = crypto.createHash('sha1').update(css).digest('hex')
themeManifestItem = _.find manifest, (item) -> return item.path is 'app/theme.css'
if not themeManifestItem?
themeManifestItem = {}
manifest.push themeManifestItem
themeManifestItem.path = 'app/theme.css'
themeManifestItem.type = 'css'
themeManifestItem.cacheable = true
themeManifestItem.where = 'client'
themeManifestItem.url = "/theme.css?#{hash}"
themeManifestItem.size = css.length
themeManifestItem.hash = hash
calculateClientHash.call this, manifest, includeFilter, runtimeConfigOverride
RocketChat.theme = new class
variables: {}
packageCallbacks: []
files: [
'server/lesshat.less'
'server/colors.less'
]
constructor: ->
@customCSS = ''
RocketChat.settings.add 'css', ''
RocketChat.settings.addGroup 'Layout'
RocketChat.settings.onload 'css', Meteor.bindEnvironment (key, value, initialLoad) =>
if not initialLoad
Meteor.startup ->
process.emit('message', {refresh: 'client'})
@compileDelayed = _.debounce Meteor.bindEnvironment(@compile.bind(@)), 100
Meteor.startup =>
RocketChat.settings.onAfterInitialLoad =>
RocketChat.settings.get '*', Meteor.bindEnvironment (key, value, initialLoad) =>
if key is 'theme-custom-css'
if value?
@customCSS = value
else if /^theme-.+/.test(key) is true
name = key.replace /^theme-[a-z]+-/, ''
if @variables[name]?
@variables[name].value = value
else
return
@compileDelayed()
compile: ->
content = [
@getVariablesAsLess()
]
content.push Assets.getText file for file in @files
for packageCallback in @packageCallbacks
result = packageCallback()
if _.isString result
content.push result
content.push @customCSS
content = content.join '\n'
options =
compress: true
plugins: [
new autoprefixer()
]
start = Date.now()
less.render content, options, (err, data) ->
logger.stop_rendering Date.now() - start
if err?
return console.log err
RocketChat.settings.updateById 'css', data.css
Meteor.startup ->
Meteor.setTimeout ->
process.emit('message', {refresh: 'client'})
, 200
addVariable: (type, name, value, section, persist=true, editor, allowedTypes) ->
@variables[name] =
type: type
value: value
if persist is true
config =
group: 'Layout'
type: type
editor: editor or type
section: section
public: false
allowedTypes: allowedTypes
RocketChat.settings.add "theme-#{type}-#{name}", value, config
addPublicColor: (name, value, section, editor='color') ->
@addVariable 'color', name, value, section, true, editor, ['color', 'expression']
addPublicFont: (name, value) ->
@addVariable 'font', name, value, 'Fonts', true
getVariablesAsObject: ->
obj = {}
for name, variable of @variables
obj[name] = variable.value
return obj
getVariablesAsLess: ->
items = []
for name, variable of @variables
items.push "@#{name}: #{variable.value};"
return items.join '\n'
addPackageAsset: (cb) ->
@packageCallbacks.push cb
@compileDelayed()
getCss: ->
return RocketChat.settings.get('css') or ''