Merge branch 'staging' of github.com:xwiki-labs/cryptpad into staging

This commit is contained in:
yflory 2017-09-13 16:20:26 +02:00
commit d360e2d0f4
34 changed files with 245 additions and 88 deletions

View File

@ -3,6 +3,7 @@
@import (once) "./modal-theme.less";
.alertify_main () {
@max-z-index: 2147483647;
@alertify-fore: @colortheme_modal-fg;
@alertify-base: @colortheme_modal-bg;
@ -27,7 +28,7 @@
// These show only once
.alertify-logs {
z-index:10000;
z-index:10000; // alertify logs
@media print {
visibility: hidden;
}
@ -63,7 +64,10 @@
bottom: 0;
width: 100%;
height: 100%;
z-index: 99999;
z-index: 99999; // alertify container
&.forefront {
z-index: @max-z-index; // alertify max forefront
}
.message {
h1, h2, h3, h4, h5, h6 {
@ -236,7 +240,7 @@
.alertify-logs {
position: fixed;
z-index: 99999;
z-index: 99999; // alertify logs
&.bottom, &:not(.top) {
bottom: 16px;

View File

@ -0,0 +1,61 @@
@import (once) "./include/colortheme.less";
@import (once) "./include/browser.less";
#cp-loading {
position: fixed;
z-index: 9999999;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
background: @colortheme_loading-bg;
color: @colortheme_loading-color;
text-align: center;
font-size: 1.5em;
.cp-loading-container {
margin-top: 50vh;
transform: translateY(-50%);
}
.cp-loading-cryptofist {
margin-left: auto;
margin-right: auto;
height: 300px;
margin-bottom: 2em;
@media screen and (max-height: @browser_media-short-screen) {
display: none;
}
}
.cp-loading-spinner-container {
position: relative;
height: 100px;
> div {
height: 100px;
}
}
}
#cp-loading-tip {
position: fixed;
z-index: 99999;
top: 80%;
left: 0;
right: 0;
text-align: center;
transition: opacity 750ms;
transition-delay: 3000ms;
@media screen and (max-height: @browser_media-medium-screen) {
display: none;
}
span {
background: @colortheme_loading-bg;
color: @colortheme_loading-color;
text-align: center;
font-size: 1.5em;
opacity: 0.7;
font-family: @colortheme_font;
padding: 15px;
max-width: 60%;
display: inline-block;
}
}

View File

@ -4,7 +4,7 @@ define([
'/common/cryptpad-common.js',
'/customize/pages.js',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
], function ($, h, Cryptpad, Pages) {
$(function () {
var $body = $('body');

View File

@ -2,7 +2,7 @@
<html class="cp-app-noscroll">
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<script async data-bootload="/code/inner.js" data-main="/common/sframe-boot.js?ver=1.1" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
<script async data-bootload="/code/inner.js" data-main="/common/sframe-boot.js?ver=1.3" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
<style>
.loading-hidden { display: none; }
#editor1 { display: none; }

View File

@ -16,7 +16,7 @@ define([
'cm/lib/codemirror',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/customize/src/less2/main.less',
'css!cm/lib/codemirror.css',

View File

@ -1,33 +1,50 @@
/*@flow*/
/*:: const define = () => {}; */
define([
'/api/config',
'/bower_components/less/dist/less.min.js'
], function (Config, Less) { /*::});module.exports = (function() {
'/api/config'
], function (Config) { /*::});module.exports = (function() {
const Config = (undefined:any);
const Less = (undefined:any);
*/
var module = { exports: {} };
var key = Config.requireConf.urlArgs;
var localStorage;
var localStorage = {};
try {
localStorage = window.localStorage || {};
if (localStorage['LESS_CACHE'] !== key) {
Object.keys(localStorage).forEach(function (k) {
if (k.indexOf('LESS_CACHE|') !== 0) { return; }
delete localStorage[k];
});
localStorage['LESS_CACHE'] = key;
}
} catch (e) {
console.error(e);
localStorage = {};
}
var fixURL = function (url) {
var mark = (url.indexOf('?') !== -1) ? '&' : '?';
return url + mark + key;
var cacheGet = function (k, cb) {
if (window.cryptpadCache) { return void window.cryptpadCache.get(k, cb); }
setTimeout(function () { cb(localStorage['LESS_CACHE|' + key + '|' + k]); })
};
var cachePut = function (k, v, cb) {
if (window.cryptpadCache) { return void window.cryptpadCache.put(k, v, cb); }
cb = cb || function () { };
setTimeout(function () { localStorage['LESS_CACHE|' + key + '|' + k] = v; cb(); });
};
var doXHR = Less.FileManager.prototype.doXHR;
Less.FileManager.prototype.doXHR = function (url, type, callback, errback) {
url = fixURL(url);
//console.log("xhr: " + url);
return doXHR(url, type, callback, errback);
var fixURL = function (url, parent) {
// data: blob: etc
if (/^[a-zA-Z0-9]*:/.test(url)) { return url; }
var ua = url.split('#');
var mark = (ua[0].indexOf('?') !== -1) ? '&' : '?';
ua[0] = ua[0] + mark + key;
if (ua[0].indexOf(':') === -1 && ua[0].indexOf('/') && parent) {
ua[0] = parent.replace(/\/[^\/]*$/, '/') + ua[0];
}
var out = ua.join('#');
//console.log(url + " --> " + out);
return out;
};
var inject = function (cssText, url) {
@ -39,31 +56,74 @@ define([
document.head.appendChild(curStyle);
};
var checkCache = function () {
if (localStorage['LESS_CACHE'] === key) { return; }
Object.keys(localStorage).forEach(function (k) {
if (k.indexOf('LESS_CACHE|') !== 0) { return; }
delete localStorage[k];
var fixAllURLs = function (source, parent) {
var urlRegEx = /@import\s*("([^"]*)"|'([^']*)')|url\s*\(\s*(\s*"([^"]*)"|'([^']*)'|[^\)]*\s*)\s*\)/ig;
var result, url;
while (!!(result = urlRegEx.exec(source))) {
url = result[3] || result[2] || result[5] || result[6] || result[4];
var newUrl = fixURL(url, parent);
var quoteLen = result[5] || result[6] ? 1 : 0;
source = source.substr(0, urlRegEx.lastIndex - url.length - quoteLen - 1)
+ newUrl + source.substr(urlRegEx.lastIndex - quoteLen - 1);
urlRegEx.lastIndex = urlRegEx.lastIndex + (newUrl.length - url.length);
}
return source;
};
var loadCSS = function (url, cb) {
var xhr = new window.XMLHttpRequest();
xhr.open("GET", fixURL(url), true);
xhr.responseType = 'text';
xhr.onload = function () {
if (/^4/.test('' + this.status)) { return cb("error loading " + url); }
cb(undefined, xhr.response);
};
xhr.send(null);
};
var lessEngine;
var getLessEngine = function (cb) {
if (lessEngine) {
cb(lessEngine);
} else {
require(['/bower_components/less/dist/less.min.js'], function (Less) {
lessEngine = Less;
var doXHR = lessEngine.FileManager.prototype.doXHR;
lessEngine.FileManager.prototype.doXHR = function (url, type, callback, errback) {
url = fixURL(url);
//console.log("xhr: " + url);
return doXHR(url, type, callback, errback);
};
cb(lessEngine);
});
}
};
var loadLess = function (url, cb) {
getLessEngine(function (less) {
less.render('@import (multiple) "' + url + '";', {}, function(err, css) {
if (err) { return void cb(err); }
cb(undefined, css.css);
}, window.less);
});
localStorage['LESS_CACHE'] = key;
};
module.exports.load = function (url /*:string*/, cb /*:()=>void*/) {
checkCache();
if (localStorage['LESS_CACHE|' + key + '|' + url]) {
inject(localStorage['LESS_CACHE|' + key + '|' + url], url);
cb();
return;
}
Less.render('@import (multiple) "' + url + '";', {}, function(err, css) {
if (err) {
console.log(err);
return;
cacheGet(url, function (css) {
if (css) {
inject(css, url);
return void cb();
}
localStorage['LESS_CACHE|' + key + '|' + url] = css.css;
inject(css.css, url);
cb();
}, window.less);
console.log('CACHE MISS ' + url);
((/\.less([\?\#].*)?$/.test(url)) ? loadLess : loadCSS)(url, function (err, css) {
var output = fixAllURLs(css, url);
cachePut(url, output);
inject(output, url);
cb();
});
});
};
return module.exports;

View File

@ -209,7 +209,15 @@ define([
return tagger;
};
UI.alert = function (msg, cb, force) {
UI.alert = function (msg, cb, opt) {
var force = false;
if (typeof(opt) === 'object') {
force = opt.force || false;
} else if (typeof(opt) === 'boolean') {
force = opt;
opt = {};
}
cb = cb || function () {};
var message;
@ -228,6 +236,7 @@ define([
dialog.nav(ok),
]);
if (opt.forefront) { $(frame).addClass('forefront'); }
var listener;
var close = Util.once(function () {
$(frame).fadeOut(150, function () { $(this).remove(); });

View File

@ -1,7 +1,37 @@
// Stage 0, this gets cached which means we can't change it. boot2-sframe.js is changable.
// Note that this file is meant to be executed only inside of a sandbox iframe.
//
// IF YOU EDIT THIS FILE, bump the version (replace 1.3 in the following command with the next version.)
// grep -nr '/common/sframe-boot.js?ver=' | sed 's/:.*$//' | while read x; do \
// sed -i -e 's@/common/sframe-boot.js?ver=[^"]*@/common/sframe-boot.js?ver=1.3@' $x; done
;(function () {
var afterLoaded = function (req) {
var localStorage = {};
if (req.cfg && req.cfg.urlArgs) {
try {
localStorage = window.localStorage;
if (localStorage['CRYPTPAD_VERSION'] !== req.cfg.urlArgs) {
// new version, flush
Object.keys(localStorage).forEach(function (k) {
if (!k.indexOf('CRYPTPAD_CACHE_')) { delete localStorage[k]; }
});
localStorage['CRYPTPAD_VERSION'] = req.cfg.urlArgs;
}
} catch (e) {
console.error(e);
localStorage = {};
}
}
window.cryptpadCache = Object.freeze({
put: function (k, v, cb) {
cb = cb || function () { };
setTimeout(function () { localStorage['CRYPTPAD_CACHE_' + k] = v; cb(); });
},
get: function (k, cb) {
if (!cb) { throw new Error(); }
setTimeout(function () { cb(localStorage['CRYPTPAD_CACHE_' + k]); });
}
});
req.cfg = req.cfg || {};
if (req.pfx) {
req.cfg.onNodeCreated = function (node /*, config, module, path*/) {

View File

@ -10,17 +10,6 @@ define(['/common/requireconfig.js'], function (RequireConfig) {
};
}
// In the event that someone clicks a link in the iframe, it's going to cause the iframe
// to navigate away from the pad which is going to be a mess. Instead we'll just reload
// the top level and then it will be simply that a link doesn't work properly.
window.onunload = function () {
window.parent.location.reload();
};
// Make sure anything which might have leaked to the localstorage is always cleaned up.
try { window.localStorage.clear(); } catch (e) { }
try { window.sessionStorage.clear(); } catch (e) { }
var mkFakeStore = function () {
var fakeStorage = {
getItem: function (k) { return fakeStorage[k]; },

View File

@ -1,7 +1,8 @@
// This file provides the API for the channel for talking to and from the sandbox iframe.
define([
'/common/sframe-protocol.js'
], function (SFrameProtocol) {
'/common/sframe-protocol.js',
'/common/common-util.js'
], function (SFrameProtocol, Util) {
var mkTxid = function () {
return Math.random().toString(16).replace('0.', '') + Math.random().toString(16).replace('0.', '');
@ -9,6 +10,7 @@ define([
var create = function (ow, cb, isSandbox) {
var otherWindow;
var evReady = Util.mkEvent(true);
var handlers = {};
var queries = {};
@ -34,11 +36,13 @@ define([
delete queries[txid];
cb(undefined, data.content, msg);
};
otherWindow.postMessage(JSON.stringify({
txid: txid,
content: content,
q: q
}), '*');
evReady.reg(function () {
otherWindow.postMessage(JSON.stringify({
txid: txid,
content: content,
q: q
}), '*');
});
};
// Fire an event. channel.event('EV_SOMETHING', { args: "whatever" });
@ -50,7 +54,9 @@ define([
if (e.indexOf('EV_') !== 0) {
throw new Error('please only use events (starting with EV_) for event messages');
}
otherWindow.postMessage(JSON.stringify({ content: content, q: e }), '*');
evReady.reg(function () {
otherWindow.postMessage(JSON.stringify({ content: content, q: e }), '*');
});
};
// Be notified on query or event. channel.on('EV_SOMETHING', function (args, reply) { ... });
@ -106,18 +112,14 @@ define([
}, true);
// Make sure both iframes are ready
var readyHandlers = [];
chan.onReady = function (h) {
if (typeof(h) !== "function") { return; }
readyHandlers.push(h);
chan.on('EV_RPC_READY', function () { h(); });
};
chan.ready = function () {
chan.whenReg('EV_RPC_READY', function () {
chan.event('EV_RPC_READY');
});
chan.on('EV_RPC_READY', function () {
readyHandlers.forEach(function (h) { h(); });
});
};
var txid;
@ -129,6 +131,7 @@ define([
//console.log(msg);
} else if (!otherWindow) {
otherWindow = ow;
evReady.fire();
ow.postMessage(JSON.stringify({ txid: data.txid }), '*');
cb(chan);
} else if (typeof(data.q) === 'string' && handlers[data.q]) {
@ -149,6 +152,7 @@ define([
if (isSandbox) {
// we're in the sandbox
otherWindow = ow;
evReady.fire();
cb(chan);
}
};

View File

@ -1,6 +1,6 @@
define([
'jquery',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'less!/contacts/main.less',
'less!/customize/src/less/toolbar.less',

View File

@ -7,7 +7,7 @@ define([
'/common/common-messenger.js',
'/contacts/messenger-ui.js',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/customize/src/less/cryptpad.less',
], function ($, Crypto, Toolbar, Cryptpad, Messenger, UI) {
var Messages = Cryptpad.Messages;

View File

@ -1,5 +1,5 @@
define([
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'less!/drive/file.less',
'less!/customize/src/less/cryptpad.less',

View File

@ -11,7 +11,7 @@ define([
'/common/cryptget.js',
'/common/mergeDrive.js',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/customize/src/less/cryptpad.less',
], function ($, Listmap, Crypto, TextPatcher, JSONSortify, Cryptpad, FO, Toolbar, AppConfig, Get, Merge) {
var module = window.MODULE = {};

View File

@ -2,7 +2,7 @@
<html class="cp-app-noscroll">
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<script async data-bootload="/file/inner.js" data-main="/common/sframe-boot.js?ver=1.1" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
<script async data-bootload="/file/inner.js" data-main="/common/sframe-boot.js?ver=1.3" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
<style>
.loading-hidden { display: none; }
#editor1 { display: none; }

View File

@ -13,7 +13,7 @@ define([
'/bower_components/file-saver/FileSaver.min.js',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/customize/src/less2/main.less',
], function (

View File

@ -2,7 +2,7 @@
<html style="height: 100%; background: transparent;">
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<script async data-bootload="/filepicker/inner.js" data-main="/common/sframe-boot.js?ver=1.1" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
<script async data-bootload="/filepicker/inner.js" data-main="/common/sframe-boot.js?ver=1.3" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
<style>
.loading-hidden { display: none; }
body #loading {

View File

@ -9,7 +9,7 @@ define([
'json.sortify',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/customize/src/less2/main.less',
], function (
$,

View File

@ -3,7 +3,7 @@ define([
'/common/cryptpad-common.js',
'/common/login.js',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
], function ($, Cryptpad, Login) {
$(function () {
var $main = $('#mainBlock');

View File

@ -3,7 +3,7 @@ define([
'cm/lib/codemirror',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'less!/code/code.less',
'less!/customize/src/less/toolbar.less',

View File

@ -10,7 +10,7 @@ define([
'/common/cryptget.js',
'/common/diffMarked.js',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/customize/src/less/cryptpad.less'
], function ($, Crypto, Realtime, TextPatcher, Toolbar, JSONSortify, JsonOT, Cryptpad,
Cryptget, DiffMd) {

View File

@ -1,6 +1,6 @@
define([
'jquery',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'less!/file/file.less',
'less!/customize/src/less/cryptpad.less',

View File

@ -12,7 +12,7 @@ define([
'/bower_components/file-saver/FileSaver.min.js',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/customize/src/less/cryptpad.less',
], function ($, Crypto, realtimeInput, Toolbar, Cryptpad, Visible, Notify, FileCrypto, MediaTag) {
var Messages = Cryptpad.Messages;

View File

@ -10,7 +10,7 @@ define([
'/common/cryptget.js',
'/slide/slide.js',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/customize/src/less/cryptpad.less',
], function ($, Crypto, Realtime, TextPatcher, Toolbar, JSONSortify, JsonOT, Cryptpad, Cryptget, Slide) {
var Messages = Cryptpad.Messages;

View File

@ -2,7 +2,7 @@
<html class="cp-app-noscroll">
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<script async data-bootload="/pad/inner.js" data-main="/common/sframe-boot.js?ver=1.2" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
<script async data-bootload="/pad/inner.js" data-main="/common/sframe-boot.js?ver=1.3" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
</head>
<body class="cp-app-pad">
<textarea style="display:none" id="editor1" name="editor1"></textarea>

View File

@ -38,7 +38,7 @@ define([
'/bower_components/diff-dom/diffDOM.js',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/customize/src/less2/main.less',
], function (
$,

View File

@ -10,7 +10,7 @@ define([
'/common/toolbar2.js',
'/bower_components/file-saver/FileSaver.min.js',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'less!/customize/src/less/toolbar.less',
'less!/customize/src/less/cryptpad.less',

View File

@ -5,7 +5,7 @@ define([
'/common/test.js',
'/common/credential.js', // preloaded for login.js
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
], function ($, Login, Cryptpad, Test, Cred) {
var Messages = Cryptpad.Messages;

View File

@ -7,7 +7,7 @@ define([
'/bower_components/file-saver/FileSaver.min.js',
'less!/customize/src/less/cryptpad.less',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'less!/customize/src/less/toolbar.less',
'less!/settings/main.less',

View File

@ -2,7 +2,7 @@
<html class="cp-app-noscroll cp-app-print">
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<script async data-bootload="/slide/inner.js" data-main="/common/sframe-boot.js?ver=1.1" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
<script async data-bootload="/slide/inner.js" data-main="/common/sframe-boot.js?ver=1.3" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
<style>
.loading-hidden { display: none; }
#editor1 { display: none; }

View File

@ -17,7 +17,7 @@ define([
'cm/lib/codemirror',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/customize/src/less2/main.less',
'css!cm/lib/codemirror.css',

View File

@ -1,6 +1,6 @@
define([
'jquery',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'less!/todo/todo.less',
//'less!/customize/src/less/cryptpad.less',

View File

@ -9,7 +9,7 @@ define([
//'/common/media-tag.js',
//'/bower_components/file-saver/FileSaver.min.js',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/customize/src/less/cryptpad.less',
], function ($, Crypto, Listmap, Toolbar, Cryptpad, Todo) {
var Messages = Cryptpad.Messages;

View File

@ -15,7 +15,7 @@ define([
'/bower_components/secure-fabric.js/dist/fabric.min.js',
'/bower_components/file-saver/FileSaver.min.js',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'less!/customize/src/less/cryptpad.less',
'less!/whiteboard/whiteboard.less',