summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--_test/tests/inc/auth_deleteprofile.test.php179
-rw-r--r--_test/tests/inc/common_ml.test.php37
-rw-r--r--_test/tests/inc/httpclient_http.test.php5
-rw-r--r--_test/tests/inc/mailer.test.php46
-rw-r--r--_test/tests/inc/tar.test.php23
-rw-r--r--_test/tests/lib/exe/fetch_imagetoken.test.php44
-rw-r--r--_test/tests/lib/exe/fetch_statuscodes_external.test.php107
-rw-r--r--inc/HTTPClient.php2
-rw-r--r--inc/Mailer.class.php31
-rw-r--r--inc/PassHash.class.php18
-rw-r--r--inc/Tar.class.php28
-rw-r--r--inc/actions.php28
-rw-r--r--inc/auth.php53
-rw-r--r--inc/common.php19
-rw-r--r--inc/confutils.php5
-rw-r--r--inc/fetch.functions.php4
-rw-r--r--inc/html.php71
-rw-r--r--inc/lang/de-informal/lang.php7
-rw-r--r--inc/lang/de/lang.php7
-rw-r--r--inc/lang/en/lang.php7
-rw-r--r--inc/lang/nl/lang.php12
-rw-r--r--inc/lang/sv/lang.php15
-rw-r--r--inc/lessc.inc.php3481
-rw-r--r--inc/load.php3
-rw-r--r--inc/media.php2
-rw-r--r--inc/template.php62
-rw-r--r--lib/exe/css.php205
-rw-r--r--lib/exe/fetch.php1
-rw-r--r--lib/exe/js.php19
-rw-r--r--lib/exe/mediamanager.php7
-rw-r--r--lib/plugins/acl/admin.php2
-rw-r--r--lib/plugins/acl/lang/nl/lang.php4
-rw-r--r--lib/plugins/acl/lang/sv/lang.php7
-rw-r--r--lib/plugins/auth.php12
-rw-r--r--lib/plugins/authad/lang/nl/settings.php5
-rw-r--r--lib/plugins/authad/lang/sv/settings.php5
-rw-r--r--lib/plugins/authldap/lang/en/settings.php2
-rw-r--r--lib/plugins/authldap/lang/nl/settings.php5
-rw-r--r--lib/plugins/authldap/lang/sv/settings.php5
-rw-r--r--lib/plugins/authmysql/lang/nl/settings.php5
-rw-r--r--lib/plugins/authmysql/lang/sv/settings.php5
-rw-r--r--lib/plugins/authpgsql/lang/nl/settings.php5
-rw-r--r--lib/plugins/authpgsql/lang/sv/settings.php5
-rw-r--r--lib/plugins/config/admin.php4
-rw-r--r--lib/plugins/config/lang/ar/lang.php2
-rw-r--r--lib/plugins/config/lang/bg/lang.php6
-rw-r--r--lib/plugins/config/lang/ca-valencia/lang.php2
-rw-r--r--lib/plugins/config/lang/ca/lang.php2
-rw-r--r--lib/plugins/config/lang/cs/lang.php2
-rw-r--r--lib/plugins/config/lang/da/lang.php2
-rw-r--r--lib/plugins/config/lang/de-informal/lang.php35
-rw-r--r--lib/plugins/config/lang/de/lang.php34
-rw-r--r--lib/plugins/config/lang/el/lang.php2
-rw-r--r--lib/plugins/config/lang/en/lang.php36
-rw-r--r--lib/plugins/config/lang/eo/lang.php2
-rw-r--r--lib/plugins/config/lang/es/lang.php2
-rw-r--r--lib/plugins/config/lang/et/lang.php2
-rw-r--r--lib/plugins/config/lang/eu/lang.php2
-rw-r--r--lib/plugins/config/lang/fa/lang.php2
-rw-r--r--lib/plugins/config/lang/fi/lang.php2
-rw-r--r--lib/plugins/config/lang/fr/lang.php2
-rw-r--r--lib/plugins/config/lang/gl/lang.php2
-rw-r--r--lib/plugins/config/lang/he/lang.php2
-rw-r--r--lib/plugins/config/lang/hu/lang.php2
-rw-r--r--lib/plugins/config/lang/ia/lang.php2
-rw-r--r--lib/plugins/config/lang/is/lang.php1
-rw-r--r--lib/plugins/config/lang/it/lang.php2
-rw-r--r--lib/plugins/config/lang/ja/lang.php2
-rw-r--r--lib/plugins/config/lang/ko/lang.php2
-rw-r--r--lib/plugins/config/lang/la/lang.php2
-rw-r--r--lib/plugins/config/lang/lv/lang.php2
-rw-r--r--lib/plugins/config/lang/mr/lang.php2
-rw-r--r--lib/plugins/config/lang/ne/lang.php2
-rw-r--r--lib/plugins/config/lang/nl/lang.php2
-rw-r--r--lib/plugins/config/lang/no/lang.php2
-rw-r--r--lib/plugins/config/lang/pl/lang.php2
-rw-r--r--lib/plugins/config/lang/pt-br/lang.php2
-rw-r--r--lib/plugins/config/lang/pt/lang.php2
-rw-r--r--lib/plugins/config/lang/ro/lang.php2
-rw-r--r--lib/plugins/config/lang/ru/lang.php2
-rw-r--r--lib/plugins/config/lang/sk/lang.php2
-rw-r--r--lib/plugins/config/lang/sl/lang.php2
-rw-r--r--lib/plugins/config/lang/sq/lang.php2
-rw-r--r--lib/plugins/config/lang/sr/lang.php2
-rw-r--r--lib/plugins/config/lang/sv/lang.php2
-rw-r--r--lib/plugins/config/lang/th/lang.php1
-rw-r--r--lib/plugins/config/lang/tr/lang.php2
-rw-r--r--lib/plugins/config/lang/uk/lang.php2
-rw-r--r--lib/plugins/config/lang/zh-tw/lang.php2
-rw-r--r--lib/plugins/config/lang/zh/lang.php2
-rw-r--r--lib/plugins/config/settings/config.class.php140
-rw-r--r--lib/plugins/config/settings/config.metadata.php57
-rw-r--r--lib/plugins/plugin/lang/nl/lang.php5
-rw-r--r--lib/plugins/plugin/lang/sv/lang.php7
-rw-r--r--lib/plugins/popularity/lang/nl/lang.php5
-rw-r--r--lib/plugins/popularity/lang/sv/lang.php8
-rw-r--r--lib/plugins/revert/admin.php2
-rw-r--r--lib/plugins/revert/lang/de-informal/intro.txt4
-rw-r--r--lib/plugins/revert/lang/de-informal/lang.php13
-rw-r--r--lib/plugins/revert/lang/de/intro.txt4
-rw-r--r--lib/plugins/revert/lang/de/lang.php9
-rw-r--r--lib/plugins/revert/lang/nl/lang.php5
-rw-r--r--lib/plugins/revert/lang/sv/lang.php9
-rw-r--r--lib/plugins/usermanager/admin.php16
-rw-r--r--lib/plugins/usermanager/lang/nl/lang.php5
-rw-r--r--lib/plugins/usermanager/lang/sv/lang.php8
-rw-r--r--lib/plugins/usermanager/style.css4
-rw-r--r--lib/scripts/linkwiz.js24
-rw-r--r--lib/scripts/toolbar.js5
-rw-r--r--lib/tpl/dokuwiki/css/_admin.css2
-rw-r--r--lib/tpl/dokuwiki/css/_diff.css2
-rw-r--r--lib/tpl/dokuwiki/css/_edit.css12
-rw-r--r--lib/tpl/dokuwiki/css/_fileuploader.css8
-rw-r--r--lib/tpl/dokuwiki/css/_footnotes.css2
-rw-r--r--lib/tpl/dokuwiki/css/_forms.css7
-rw-r--r--lib/tpl/dokuwiki/css/_media_fullscreen.css40
-rw-r--r--lib/tpl/dokuwiki/css/_media_popup.css12
-rw-r--r--lib/tpl/dokuwiki/css/_modal.css10
-rw-r--r--lib/tpl/dokuwiki/css/_search.css6
-rw-r--r--lib/tpl/dokuwiki/css/_tabs.css14
-rw-r--r--lib/tpl/dokuwiki/css/_toc.css2
-rw-r--r--lib/tpl/dokuwiki/css/basic.less (renamed from lib/tpl/dokuwiki/css/basic.css)48
-rw-r--r--lib/tpl/dokuwiki/css/content.less (renamed from lib/tpl/dokuwiki/css/content.css)317
-rw-r--r--lib/tpl/dokuwiki/css/design.css405
-rw-r--r--lib/tpl/dokuwiki/css/design.less439
-rw-r--r--lib/tpl/dokuwiki/css/includes.css4
-rw-r--r--lib/tpl/dokuwiki/css/mixins.less10
-rw-r--r--lib/tpl/dokuwiki/css/mobile.less (renamed from lib/tpl/dokuwiki/css/mobile.css)62
-rw-r--r--lib/tpl/dokuwiki/css/pagetools.css424
-rw-r--r--lib/tpl/dokuwiki/css/pagetools.less233
-rw-r--r--lib/tpl/dokuwiki/css/structure.css81
-rw-r--r--lib/tpl/dokuwiki/css/structure.less89
-rw-r--r--lib/tpl/dokuwiki/style.ini52
133 files changed, 5690 insertions, 1713 deletions
diff --git a/_test/tests/inc/auth_deleteprofile.test.php b/_test/tests/inc/auth_deleteprofile.test.php
new file mode 100644
index 000000000..dc38fcd16
--- /dev/null
+++ b/_test/tests/inc/auth_deleteprofile.test.php
@@ -0,0 +1,179 @@
+<?php
+
+class Mock_Auth_Plugin extends DokuWiki_Auth_Plugin {
+
+ public $loggedOff = false;
+
+ public function __construct($canDeleteUser = true) {
+ $this->cando['delUser'] = $canDeleteUser;
+ }
+
+ public function checkPass($user, $pass) {
+ return $pass == 'password';
+ }
+
+ public function deleteUsers($users) {
+ return in_array($_SERVER['REMOTE_USER'], $users);
+ }
+
+ public function logoff() {
+ $this->loggedOff = true;
+ }
+
+}
+
+class auth_deleteprofile_test extends DokuWikiTest {
+
+ /*
+ * Tests:
+ *
+ * 1. It works and the user is logged off
+ * 2. Password matches when config requires it
+ * 3,4. Auth plugin can prevent & wiki config can prevent
+ * 5. Any of invalid security token, missing/not set 'delete' flag, missing/unchecked 'confirm_delete'
+ *
+ */
+
+ function test_success() {
+
+ global $ACT, $INPUT, $conf, $auth;
+
+ $ACT = 'profile_delete';
+ $conf['profileconfirm'] = false;
+ $_SERVER['REMOTE_USER'] = 'testuser';
+
+ $input = array(
+ 'do' => $ACT,
+ 'sectok' => getSecurityToken(),
+ 'delete' => '1',
+ 'confirm_delete' => '1',
+ );
+
+ $_POST = $input;
+ $_REQUEST = $input;
+ $INPUT = new Input();
+
+ $auth = new Mock_Auth_Plugin();
+
+ $this->assertTrue(auth_deleteprofile());
+ $this->assertTrue($auth->loggedOff);
+ }
+
+ function test_confirmation_required() {
+
+ global $ACT, $INPUT, $conf, $auth;
+
+ $ACT = 'profile_delete';
+ $conf['profileconfirm'] = true;
+ $_SERVER['REMOTE_USER'] = 'testuser';
+
+ $input = array(
+ 'do' => $ACT,
+ 'sectok' => getSecurityToken(),
+ 'delete' => '1',
+ 'confirm_delete' => '1',
+ 'oldpass' => 'wrong',
+ );
+
+ $_POST = $input;
+ $_REQUEST = $input;
+ $INPUT = new Input();
+
+ $auth = new Mock_Auth_Plugin();
+
+ // password check required - it fails, so don't delete profile
+ $this->assertFalse(auth_deleteprofile());
+
+ // now it passes, we're good to go
+ $INPUT->set('oldpass','password');
+ $INPUT->post->set('oldpass','password');
+ $this->assertTrue(auth_deleteprofile());
+ }
+
+ function test_authconfig_prevents() {
+
+ global $ACT, $INPUT, $conf, $auth;
+
+ $ACT = 'profile_delete';
+ $conf['profileconfirm'] = false;
+ $_SERVER['REMOTE_USER'] = 'testuser';
+
+ $input = array(
+ 'do' => $ACT,
+ 'sectok' => getSecurityToken(),
+ 'delete' => '1',
+ 'confirm_delete' => '1',
+ );
+
+ $_POST = $input;
+ $_REQUEST = $input;
+ $INPUT = new Input();
+
+ $auth = new Mock_Auth_Plugin(false);
+ $conf['disableactions'] = '';
+ $this->assertFalse(auth_deleteprofile());
+ }
+
+ function test_wikiconfig_prevents() {
+
+ global $ACT, $INPUT, $conf, $auth;
+
+ $ACT = 'profile_delete';
+ $conf['profileconfirm'] = false;
+ $_SERVER['REMOTE_USER'] = 'testuser';
+
+ $input = array(
+ 'do' => $ACT,
+ 'sectok' => getSecurityToken(),
+ 'delete' => '1',
+ 'confirm_delete' => '1',
+ );
+
+ $_POST = $input;
+ $_REQUEST = $input;
+ $INPUT = new Input();
+
+ $auth = new Mock_Auth_Plugin();
+ $conf['disableactions'] = 'profile_delete';
+
+ $this->assertFalse(actionOK('profile_delete'));
+ $this->assertTrue($auth->canDo('delUser'));
+
+ $this->assertFalse(auth_deleteprofile());
+ }
+
+ function test_basic_parameters() {
+
+ global $ACT, $INPUT, $conf, $auth;
+
+ $ACT = 'profile_delete';
+ $conf['profileconfirm'] = true;
+ $_SERVER['REMOTE_USER'] = 'testuser';
+
+ $input = array(
+ 'do' => $ACT,
+ 'sectok' => getSecurityToken(),
+ 'delete' => '1',
+ 'confirm_delete' => '1',
+ 'oldpass' => 'password',
+ );
+
+ $_POST = $input;
+ $_REQUEST = $input;
+ $input_foundation = new Input();
+
+ $auth = new Mock_Auth_Plugin();
+
+ $INPUT = clone $input_foundation;
+ $INPUT->remove('delete');
+ $this->assertFalse(auth_deleteprofile());
+
+ $INPUT = clone $input_foundation;
+ $INPUT->set('sectok','wrong');
+ $this->assertFalse(auth_deleteprofile());
+
+ $INPUT = clone $input_foundation;
+ $INPUT->remove('confirm_delete');
+ $this->assertFalse(auth_deleteprofile());
+ }
+} \ No newline at end of file
diff --git a/_test/tests/inc/common_ml.test.php b/_test/tests/inc/common_ml.test.php
index 6f3b71db4..415c0a88d 100644
--- a/_test/tests/inc/common_ml.test.php
+++ b/_test/tests/inc/common_ml.test.php
@@ -90,6 +90,25 @@ class common_ml_test extends DokuWikiTest {
$this->assertEquals($expect, ml($id, $args));
}
+ function test_ml_img_external() {
+ global $conf;
+ $conf['useslash'] = 0;
+ $conf['userewrite'] = 0;
+
+ $ids = array(
+ 'https://example.com/lib/tpl/dokuwiki/images/logo.png',
+ 'http://example.com/lib/tpl/dokuwiki/images/logo.png',
+ 'ftp://example.com/lib/tpl/dokuwiki/images/logo.png'
+ );
+
+ foreach($ids as $id) {
+ $tok = media_get_token($id, 0, 0);
+
+ $expect = DOKU_BASE.$this->script.'?tok='.$tok.'&amp;media='.rawurlencode($id);
+ $this->assertEquals($expect, ml($id));
+ }
+ }
+
function test_ml_imgresize_array_external() {
global $conf;
$conf['useslash'] = 0;
@@ -107,8 +126,24 @@ class common_ml_test extends DokuWikiTest {
$tok = media_get_token($id, $w, 0);
$hash = substr(PassHash::hmac('md5', $id, auth_cookiesalt()), 0, 6);
- $expect = DOKU_BASE.$this->script.'?hash='.$hash.'&amp;w='.$w.'&amp;tok='.$tok.'&amp;media='.rawurlencode($id);
+ $expect = DOKU_BASE.$this->script.'?w='.$w.'&amp;tok='.$tok.'&amp;media='.rawurlencode($id);
$this->assertEquals($expect, ml($id, $args));
}
+
+ $h = 50;
+ $args = array('h' => $h);
+ $tok = media_get_token($id, $h, 0);
+
+ $expect = DOKU_BASE.$this->script.'?h='.$h.'&amp;tok='.$tok.'&amp;media='.rawurlencode($id);
+ $this->assertEquals($expect, ml($id, $args));
+
+ $w = 80;
+ $h = 50;
+ $args = array('w' => $w, 'h' => $h);
+ $tok = media_get_token($id, $w, $h);
+
+ $expect = DOKU_BASE.$this->script.'?w='.$w.'&amp;h='.$h.'&amp;tok='.$tok.'&amp;media='.rawurlencode($id);
+ $this->assertEquals($expect, ml($id, $args));
+
}
}
diff --git a/_test/tests/inc/httpclient_http.test.php b/_test/tests/inc/httpclient_http.test.php
index 522f0790c..43dd4478f 100644
--- a/_test/tests/inc/httpclient_http.test.php
+++ b/_test/tests/inc/httpclient_http.test.php
@@ -122,9 +122,14 @@ class httpclient_http_test extends DokuWikiTest {
function test_maxbody(){
$http = new HTTPClient();
$http->max_bodysize = 250;
+
+ // this should abort completely
$data = $http->get($this->server.'/stream/30');
$this->assertTrue($data === false, 'HTTP response');
+
+ // this should read just the needed bytes
$http->max_bodysize_abort = false;
+ $http->keep_alive = false;
$data = $http->get($this->server.'/stream/30');
$this->assertFalse($data === false, 'HTTP response');
/* should read no more than max_bodysize+1 */
diff --git a/_test/tests/inc/mailer.test.php b/_test/tests/inc/mailer.test.php
index 053e216b8..ef78692b3 100644
--- a/_test/tests/inc/mailer.test.php
+++ b/_test/tests/inc/mailer.test.php
@@ -15,6 +15,11 @@ class TestMailer extends Mailer {
public function prepareHeaders() {
return parent::prepareHeaders();
}
+
+ public function cleanHeaders() {
+ parent::cleanHeaders();
+ }
+
}
class mailer_test extends DokuWikiTest {
@@ -67,6 +72,47 @@ class mailer_test extends DokuWikiTest {
$this->assertArrayNotHasKey('Test-Header',$headers);
}
+ function test_addresses(){
+ $mail = new TestMailer();
+
+ $mail->to('andi@splitbrain.org');
+ $mail->cleanHeaders();
+ $headers = $mail->prop('headers');
+ $this->assertEquals('andi@splitbrain.org', $headers['To']);
+
+ $mail->to('<andi@splitbrain.org>');
+ $mail->cleanHeaders();
+ $headers = $mail->prop('headers');
+ $this->assertEquals('andi@splitbrain.org', $headers['To']);
+
+ $mail->to('Andreas Gohr <andi@splitbrain.org>');
+ $mail->cleanHeaders();
+ $headers = $mail->prop('headers');
+ $this->assertEquals('Andreas Gohr <andi@splitbrain.org>', $headers['To']);
+
+ $mail->to('Andreas Gohr <andi@splitbrain.org> , foo <foo@example.com>');
+ $mail->cleanHeaders();
+ $headers = $mail->prop('headers');
+ $this->assertEquals('Andreas Gohr <andi@splitbrain.org>, foo <foo@example.com>', $headers['To']);
+
+ $mail->to('Möp <moep@example.com> , foo <foo@example.com>');
+ $mail->cleanHeaders();
+ $headers = $mail->prop('headers');
+ $this->assertEquals('=?UTF-8?B?TcO2cA==?= <moep@example.com>, foo <foo@example.com>', $headers['To']);
+
+ $mail->to(array('Möp <moep@example.com> ',' foo <foo@example.com>'));
+ $mail->cleanHeaders();
+ $headers = $mail->prop('headers');
+ $this->assertEquals('=?UTF-8?B?TcO2cA==?= <moep@example.com>, foo <foo@example.com>', $headers['To']);
+
+ $mail->to(array('Beet, L van <lvb@example.com>',' foo <foo@example.com>'));
+ $mail->cleanHeaders();
+ $headers = $mail->prop('headers');
+ $this->assertEquals('=?UTF-8?B?QmVldCwgTCB2YW4=?= <lvb@example.com>, foo <foo@example.com>', $headers['To']);
+
+
+ }
+
function test_simplemail(){
global $conf;
$conf['htmlmail'] = 0;
diff --git a/_test/tests/inc/tar.test.php b/_test/tests/inc/tar.test.php
index 9801ca1e0..417f1a853 100644
--- a/_test/tests/inc/tar.test.php
+++ b/_test/tests/inc/tar.test.php
@@ -58,6 +58,8 @@ class Tar_TestCase extends DokuWikiTest {
$tar->addData('another/testdata3.txt', 'testcontent3');
$tar->close();
+copy ($tmp, '/tmp/test.tar');
+
$this->assertTrue(filesize($tmp) > 30); //arbitrary non-zero number
$data = file_get_contents($tmp);
@@ -66,7 +68,7 @@ class Tar_TestCase extends DokuWikiTest {
$this->assertTrue(strpos($data, 'testcontent3') !== false, 'Content in TAR');
// fullpath might be too long to be stored as full path FS#2802
- $this->assertTrue(strpos($data, "$tdir") !== false, 'Path in TAR');
+ $this->assertTrue(strpos($data, "$tdir") !== false, "Path in TAR '$tdir'");
$this->assertTrue(strpos($data, "testdata1.txt") !== false, 'File in TAR');
$this->assertTrue(strpos($data, 'noway/testdata2.txt') !== false, 'Path in TAR');
@@ -396,4 +398,23 @@ class Tar_TestCase extends DokuWikiTest {
$this->assertEquals(512*4, strlen($file)); // 1 header block + data block + 2 footer blocks
}
+
+
+ public function test_cleanPath(){
+ $tar = new Tar();
+ $tests = array (
+ '/foo/bar' => 'foo/bar',
+ '/foo/bar/' => 'foo/bar',
+ 'foo//bar' => 'foo/bar',
+ 'foo/0/bar' => 'foo/0/bar',
+ 'foo/../bar' => 'bar',
+ 'foo/bang/bang/../../bar' => 'foo/bar',
+ 'foo/../../bar' => 'bar',
+ 'foo/.././../bar' => 'bar',
+ );
+
+ foreach($tests as $in => $out){
+ $this->assertEquals($out, $tar->cleanPath($in), "Input: $in");
+ }
+ }
}
diff --git a/_test/tests/lib/exe/fetch_imagetoken.test.php b/_test/tests/lib/exe/fetch_imagetoken.test.php
index 9e5b6e4a2..99e642557 100644
--- a/_test/tests/lib/exe/fetch_imagetoken.test.php
+++ b/_test/tests/lib/exe/fetch_imagetoken.test.php
@@ -23,10 +23,10 @@ class fetch_imagetoken_test extends DokuWikiTest {
parent::setUp();
global $conf;
- $conf['sendfile'] = 0;
+ $conf['xsendfile'] = 0;
global $MIME, $EXT, $CACHE, $INPUT; // variables fetch creates in global scope -- should this be in fetch?
- }
+ }
function getUri() {
$w = $this->width ? 'w='.$this->width.'&' : '';
@@ -39,14 +39,14 @@ class fetch_imagetoken_test extends DokuWikiTest {
$request = new TestRequest();
return $request->get(array(),str_replace('{%token%}',$token,$this->getUri()));
}
-
- /**
+
+ /**
* modified image request with valid token
* expect: header with mime-type
* expect: content
* expect: no error response
- */
- function test_valid_token(){
+ */
+ function test_valid_token(){
$valid_token = 'tok='.media_get_token($this->media, $this->width, $this->height).'&';
$response = $this->fetchResponse($valid_token);
$this->assertTrue((bool)$response->getHeader('Content-Type'));
@@ -54,24 +54,24 @@ class fetch_imagetoken_test extends DokuWikiTest {
$status_code = $response->getStatusCode();
$this->assertTrue(is_null($status_code) || (200 == $status_code));
- }
-
- /**
+ }
+
+ /**
* modified image request with invalid token
- * expect: 412 status code
- */
- function test_invalid_token(){
- $invalid_token = 'tok='.media_get_token('junk',200,100).'&';
- $this->assertEquals(412,$this->fetchResponse($invalid_token)->getStatusCode());
- }
-
- /**
- * modified image request with no token
* expect: 412 status code
- */
- function test_missing_token(){
- $no_token = '';
- $this->assertEquals(412,$this->fetchResponse($notoken)->getStatusCode());
+ */
+ function test_invalid_token(){
+ $invalid_token = 'tok='.media_get_token('junk',200,100).'&';
+ $this->assertEquals(412,$this->fetchResponse($invalid_token)->getStatusCode());
+ }
+
+ /**
+ * modified image request with no token
+ * expect: 412 status code
+ */
+ function test_missing_token(){
+ $no_token = '';
+ $this->assertEquals(412,$this->fetchResponse($no_token)->getStatusCode());
}
/**
diff --git a/_test/tests/lib/exe/fetch_statuscodes_external.test.php b/_test/tests/lib/exe/fetch_statuscodes_external.test.php
new file mode 100644
index 000000000..79a45ec93
--- /dev/null
+++ b/_test/tests/lib/exe/fetch_statuscodes_external.test.php
@@ -0,0 +1,107 @@
+<?php
+
+/**
+ * @group internet
+ */
+class fetch_statuscodes_external_test extends DokuWikiTest {
+
+ private $media = 'http://www.google.com/images/srpr/logo3w.png'; //used in media_get_from_url test too
+ private $width = 200;
+ private $height = 0;
+
+ function setUp() {
+
+ header('X-Test: check headers working');
+ $header_check = function_exists('xdebug_get_headers') ? xdebug_get_headers() : headers_list();
+ if(empty($header_check)) {
+ $this->markTestSkipped('headers not returned, perhaps your sapi does not return headers, try xdebug');
+ } else {
+ header_remove('X-Test');
+ }
+
+ parent::setUp();
+
+ global $conf;
+ $conf['fetchsize'] = 500 * 1024; //500kb
+ $conf['xsendfile'] = 0;
+
+ global $MIME, $EXT, $CACHE, $INPUT; // variables fetch creates in global scope -- should this be in fetch?
+ }
+
+ function getUri() {
+ $w = $this->width ? 'w='.$this->width.'&' : '';
+ $h = $this->height ? 'h='.$this->height.'&' : '';
+ return '/lib/exe/fetch.php?'.$w.$h.'{%token%}media='.rawurlencode($this->media);
+ }
+
+ function fetchResponse($token) {
+ $request = new TestRequest();
+ return $request->get(array(), str_replace('{%token%}', $token, $this->getUri()));
+ }
+
+ /**
+ * modified image request with valid token
+ * and not-modified image request with valid token
+ *
+ * expect: header with mime-type
+ * expect: content
+ * expect: no error response
+ */
+ function test_valid_token() {
+ $valid_token_resize = 'tok='.media_get_token($this->media, $this->width, $this->height).'&';
+
+ $this->handlevalidresponse($valid_token_resize);
+
+ //original size
+ $this->width = $this->height = 0;
+ $valid_token_original = 'tok='.media_get_token($this->media, $this->width, $this->height).'&';
+
+ $this->handlevalidresponse($valid_token_original);
+
+ }
+
+ /**
+ * Performs asserts for valid request
+ *
+ * @param $valid_token
+ */
+ private function handlevalidresponse($valid_token){
+ $response = $this->fetchResponse($valid_token);
+ $this->assertTrue((bool) $response->getHeader('Content-Type'));
+ $this->assertTrue((bool) ($response->getContent()));
+
+ $status_code = $response->getStatusCode();
+ $this->assertTrue(is_null($status_code) || (200 == $status_code));
+ }
+
+ /**
+ * modified image request with invalid token
+ * expect: 412 status code
+ */
+ function test_invalid_token() {
+ $invalid_tokens = array(
+ 'invalid_token_wrongid' => media_get_token('junk', 200, 100),
+ 'invalid_token_wrongh' => media_get_token($this->media, 200, 10),
+ 'invalid_token_wrongw' => media_get_token($this->media, 20, 100),
+ 'invalid_token_wrongwh' => media_get_token($this->media, 20, 10)
+ );
+ foreach($invalid_tokens as $invalid_token)
+ $this->assertEquals(412, $this->fetchResponse('tok='.$invalid_token.'&')->getStatusCode());
+
+ }
+
+ /**
+ * modified image request with no token
+ * and not modified image with no token
+ * expect: 412 status code
+ */
+ function test_missing_token() {
+ $no_token = '';
+
+ $this->assertEquals(412, $this->fetchResponse($no_token)->getStatusCode());
+
+ $this->width = $this->height = 0;
+ $this->assertEquals(412, $this->fetchResponse($no_token)->getStatusCode());
+ }
+}
+//Setup VIM: ex: et ts=4 :
diff --git a/inc/HTTPClient.php b/inc/HTTPClient.php
index 3964c8fbc..b2621bdbb 100644
--- a/inc/HTTPClient.php
+++ b/inc/HTTPClient.php
@@ -463,6 +463,8 @@ class HTTPClient {
}
$r_body = $this->_readData($socket, $length, 'response (content-length limited)', true);
+ }elseif( !isset($this->resp_headers['transfer-encoding']) && $this->max_bodysize && !$this->keep_alive){
+ $r_body = $this->_readData($socket, $this->max_bodysize, 'response (content-length limited)', true);
}else{
// read entire socket
$r_size = 0;
diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php
index cb5f22f54..0f3321bb9 100644
--- a/inc/Mailer.class.php
+++ b/inc/Mailer.class.php
@@ -137,7 +137,13 @@ class Mailer {
}
// empty value deletes
- $value = trim($value);
+ if(is_array($value)){
+ $value = array_map('trim', $value);
+ $value = array_filter($value);
+ if(!$value) $value = '';
+ }else{
+ $value = trim($value);
+ }
if($value === '') {
if(isset($this->headers[$header])) unset($this->headers[$header]);
} else {
@@ -270,7 +276,7 @@ class Mailer {
* Add the To: recipients
*
* @see setAddress
- * @param string $address Multiple adresses separated by commas
+ * @param string|array $address Multiple adresses separated by commas or as array
*/
public function to($address) {
$this->setHeader('To', $address, false);
@@ -280,7 +286,7 @@ class Mailer {
* Add the Cc: recipients
*
* @see setAddress
- * @param string $address Multiple adresses separated by commas
+ * @param string|array $address Multiple adresses separated by commas or as array
*/
public function cc($address) {
$this->setHeader('Cc', $address, false);
@@ -290,7 +296,7 @@ class Mailer {
* Add the Bcc: recipients
*
* @see setAddress
- * @param string $address Multiple adresses separated by commas
+ * @param string|array $address Multiple adresses separated by commas or as array
*/
public function bcc($address) {
$this->setHeader('Bcc', $address, false);
@@ -327,18 +333,20 @@ class Mailer {
* Example:
* setAddress("föö <foo@bar.com>, me@somewhere.com","TBcc");
*
- * @param string $address Multiple adresses separated by commas
+ * @param string|array $address Multiple adresses separated by commas or as array
* @return bool|string the prepared header (can contain multiple lines)
*/
- public function cleanAddress($address) {
+ public function cleanAddress($addresses) {
// No named recipients for To: in Windows (see FS#652)
$names = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? false : true;
- $address = preg_replace('/[\r\n\0]+/', ' ', $address); // remove attack vectors
-
$headers = '';
- $parts = explode(',', $address);
- foreach($parts as $part) {
+ if(!is_array($addresses)){
+ $addresses = explode(',', $addresses);
+ }
+
+ foreach($addresses as $part) {
+ $part = preg_replace('/[\r\n\0]+/', ' ', $part); // remove attack vectors
$part = trim($part);
// parse address
@@ -378,7 +386,7 @@ class Mailer {
$text = utf8_strip($text);
}
- if(!utf8_isASCII($text)) {
+ if(strpos($text, ',') !== false || !utf8_isASCII($text)) {
$text = '=?UTF-8?B?'.base64_encode($text).'?=';
}
} else {
@@ -392,6 +400,7 @@ class Mailer {
$headers .= $text.' '.$addr;
}
+ $headers = trim($headers);
if(empty($headers)) return false;
return $headers;
diff --git a/inc/PassHash.class.php b/inc/PassHash.class.php
index 607661a22..db6a3a77c 100644
--- a/inc/PassHash.class.php
+++ b/inc/PassHash.class.php
@@ -98,7 +98,7 @@ class PassHash {
$salt = '';
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
for($i = 0; $i < $len; $i++) {
- $salt .= $chars[auth_random(0, 61)];
+ $salt .= $chars[$this->random(0, 61)];
}
return $salt;
}
@@ -541,4 +541,20 @@ class PassHash {
return ($raw_output) ? pack($pack, $output) : $output;
}
+
+ /**
+ * Use DokuWiki's secure random generator if available
+ *
+ * @param $min
+ * @param $max
+ *
+ * @return int
+ */
+ protected function random($min, $max){
+ if(function_exists('auth_random')){
+ return auth_random($min, $max);
+ }else{
+ return mt_rand($min, $max);
+ }
+ }
}
diff --git a/inc/Tar.class.php b/inc/Tar.class.php
index d1a38ea0e..bc87d7d29 100644
--- a/inc/Tar.class.php
+++ b/inc/Tar.class.php
@@ -568,29 +568,23 @@ class Tar {
}
/**
- * Cleans up a path and removes relative parts
+ * Cleans up a path and removes relative parts, also strips leading slashes
*
* @param string $p_dir
* @return string
*/
- protected function cleanPath($p_dir) {
- $r = '';
- if($p_dir) {
- $subf = explode("/", $p_dir);
-
- for($i = count($subf) - 1; $i >= 0; $i--) {
- if($subf[$i] == ".") {
- # do nothing
- } elseif($subf[$i] == "..") {
- $i--;
- } elseif(!$subf[$i] && $i != count($subf) - 1 && $i) {
- # do nothing
- } else {
- $r = $subf[$i].($i != (count($subf) - 1) ? "/".$r : "");
- }
+ public function cleanPath($path) {
+ $path=explode('/', $path);
+ $newpath=array();
+ foreach($path as $p) {
+ if ($p === '' || $p === '.') continue;
+ if ($p==='..') {
+ array_pop($newpath);
+ continue;
}
+ array_push($newpath, $p);
}
- return $r;
+ return trim(implode('/', $newpath), '/');
}
/**
diff --git a/inc/actions.php b/inc/actions.php
index da3414eb2..bf124c887 100644
--- a/inc/actions.php
+++ b/inc/actions.php
@@ -92,14 +92,26 @@ function act_dispatch(){
$ACT = 'login';
}
- //update user profile
- if ($ACT == 'profile') {
+ // user profile changes
+ if (in_array($ACT, array('profile','profile_delete'))) {
if(!$_SERVER['REMOTE_USER']) {
$ACT = 'login';
} else {
- if(updateprofile()) {
- msg($lang['profchanged'],1);
- $ACT = 'show';
+ switch ($ACT) {
+ case 'profile' :
+ if(updateprofile()) {
+ msg($lang['profchanged'],1);
+ $ACT = 'show';
+ }
+ break;
+ case 'profile_delete' :
+ if(auth_deleteprofile()){
+ msg($lang['profdeleted'],1);
+ $ACT = 'show';
+ } else {
+ $ACT = 'profile';
+ }
+ break;
}
}
}
@@ -247,7 +259,7 @@ function act_validate($act) {
//disable all acl related commands if ACL is disabled
if(!$conf['useacl'] && in_array($act,array('login','logout','register','admin',
'subscribe','unsubscribe','profile','revert',
- 'resendpwd'))){
+ 'resendpwd','profile_delete'))){
msg('Command unavailable: '.htmlspecialchars($act),-1);
return 'show';
}
@@ -258,7 +270,7 @@ function act_validate($act) {
if(!in_array($act,array('login','logout','register','save','cancel','edit','draft',
'preview','search','show','check','index','revisions',
'diff','recent','backlink','admin','subscribe','revert',
- 'unsubscribe','profile','resendpwd','recover',
+ 'unsubscribe','profile','profile_delete','resendpwd','recover',
'draftdel','sitemap','media')) && substr($act,0,7) != 'export_' ) {
msg('Command unknown: '.htmlspecialchars($act),-1);
return 'show';
@@ -287,7 +299,7 @@ function act_permcheck($act){
}else{
$permneed = AUTH_CREATE;
}
- }elseif(in_array($act,array('login','search','recent','profile','index', 'sitemap'))){
+ }elseif(in_array($act,array('login','search','recent','profile','profile_delete','index', 'sitemap'))){
$permneed = AUTH_NONE;
}elseif($act == 'revert'){
$permneed = AUTH_ADMIN;
diff --git a/inc/auth.php b/inc/auth.php
index a1c92ec80..1c0bf5b4f 100644
--- a/inc/auth.php
+++ b/inc/auth.php
@@ -136,22 +136,30 @@ function auth_loadACL() {
$acl = file($config_cascade['acl']['default']);
- //support user wildcard
$out = array();
foreach($acl as $line) {
$line = trim($line);
if($line{0} == '#') continue;
list($id,$rest) = preg_split('/\s+/',$line,2);
+ // substitue user wildcard first (its 1:1)
+ if(strstr($line, '%USER%')){
+ // if user is not logged in, this ACL line is meaningless - skip it
+ if (!isset($_SERVER['REMOTE_USER'])) continue;
+
+ $id = str_replace('%USER%',cleanID($_SERVER['REMOTE_USER']),$id);
+ $rest = str_replace('%USER%',auth_nameencode($_SERVER['REMOTE_USER']),$rest);
+ }
+
+ // substitute group wildcard (its 1:m)
if(strstr($line, '%GROUP%')){
+ // if user is not logged in, grps is empty, no output will be added (i.e. skipped)
foreach((array) $USERINFO['grps'] as $grp){
$nid = str_replace('%GROUP%',cleanID($grp),$id);
$nrest = str_replace('%GROUP%','@'.auth_nameencode($grp),$rest);
$out[] = "$nid\t$nrest";
}
} else {
- $id = str_replace('%USER%',cleanID($_SERVER['REMOTE_USER']),$id);
- $rest = str_replace('%USER%',auth_nameencode($_SERVER['REMOTE_USER']),$rest);
$out[] = "$id\t$rest";
}
}
@@ -1042,6 +1050,45 @@ function updateprofile() {
return false;
}
+function auth_deleteprofile(){
+ global $conf;
+ global $lang;
+ /* @var DokuWiki_Auth_Plugin $auth */
+ global $auth;
+ /* @var Input $INPUT */
+ global $INPUT;
+
+ if(!$INPUT->post->bool('delete')) return false;
+ if(!checkSecurityToken()) return false;
+
+ // action prevented or auth module disallows
+ if(!actionOK('profile_delete') || !$auth->canDo('delUser')) {
+ msg($lang['profnodelete'], -1);
+ return false;
+ }
+
+ if(!$INPUT->post->bool('confirm_delete')){
+ msg($lang['profconfdeletemissing'], -1);
+ return false;
+ }
+
+ if($conf['profileconfirm']) {
+ if(!$auth->checkPass($_SERVER['REMOTE_USER'], $INPUT->post->str('oldpass'))) {
+ msg($lang['badpassconfirm'], -1);
+ return false;
+ }
+ }
+
+ $deleted[] = $_SERVER['REMOTE_USER'];
+ if($auth->triggerUserMod('delete', array($deleted))) {
+ // force and immediate logout including removing the sticky cookie
+ auth_logoff();
+ return true;
+ }
+
+ return false;
+}
+
/**
* Send a new password
*
diff --git a/inc/common.php b/inc/common.php
index bff6e80de..3312141c8 100644
--- a/inc/common.php
+++ b/inc/common.php
@@ -148,7 +148,7 @@ function pageinfo() {
$info['id'] = $ID;
$info['rev'] = $REV;
- if(isset($_SERVER['REMOTE_USER'])) {
+ if(isset($_SERVER['REMOTE_USER'])) {
$sub = new Subscription();
$info['subscribed'] = $sub->user_subscription();
} else {
@@ -474,7 +474,7 @@ function ml($id = '', $more = '', $direct = true, $sep = '&amp;', $abs = false)
if(is_array($more)) {
// add token for resized images
- if($more['w'] || $more['h']){
+ if($more['w'] || $more['h'] || $isexternalimage){
$more['tok'] = media_get_token($id,$more['w'],$more['h']);
}
// strip defaults for shorter URLs
@@ -485,12 +485,13 @@ function ml($id = '', $more = '', $direct = true, $sep = '&amp;', $abs = false)
$more = buildURLparams($more, $sep);
} else {
$matches = array();
- if (preg_match_all('/\b(w|h)=(\d*)\b/',$more,$matches,PREG_SET_ORDER)){
+ if (preg_match_all('/\b(w|h)=(\d*)\b/',$more,$matches,PREG_SET_ORDER) || $isexternalimage){
$resize = array('w'=>0, 'h'=>0);
foreach ($matches as $match){
$resize[$match[1]] = $match[2];
}
- $more .= $sep.'tok='.media_get_token($id,$resize['w'],$resize['h']);
+ $more .= $more === '' ? '' : $sep;
+ $more .= 'tok='.media_get_token($id,$resize['w'],$resize['h']);
}
$more = str_replace('cache=cache', '', $more); //skip default
$more = str_replace(',,', ',', $more);
@@ -506,14 +507,8 @@ function ml($id = '', $more = '', $direct = true, $sep = '&amp;', $abs = false)
// external URLs are always direct without rewriting
if($isexternalimage) {
$xlink .= 'lib/exe/fetch.php';
- // add hash:
- $xlink .= '?hash='.substr(PassHash::hmac('md5', $id, auth_cookiesalt()), 0, 6);
- if($more) {
- $xlink .= $sep.$more;
- $xlink .= $sep.'media='.rawurlencode($id);
- } else {
- $xlink .= $sep.'media='.rawurlencode($id);
- }
+ $xlink .= '?'.$more;
+ $xlink .= $sep.'media='.rawurlencode($id);
return $xlink;
}
diff --git a/inc/confutils.php b/inc/confutils.php
index 404cc6050..0ac003b72 100644
--- a/inc/confutils.php
+++ b/inc/confutils.php
@@ -241,7 +241,7 @@ function getConfigFiles($type) {
*/
function actionOK($action){
static $disabled = null;
- if(is_null($disabled)){
+ if(is_null($disabled) || defined('SIMPLE_TEST')){
global $conf;
/** @var auth_basic $auth */
global $auth;
@@ -261,6 +261,9 @@ function actionOK($action){
if (is_null($auth) || !$auth->canDo('Profile')) {
$disabled[] = 'profile';
}
+ if (is_null($auth) || !$auth->canDo('delUser')) {
+ $disabled[] = 'profile_delete';
+ }
if (is_null($auth)) {
$disabled[] = 'login';
}
diff --git a/inc/fetch.functions.php b/inc/fetch.functions.php
index 53ade3555..207ad9e5f 100644
--- a/inc/fetch.functions.php
+++ b/inc/fetch.functions.php
@@ -101,8 +101,8 @@ function checkFileStatus(&$media, &$file, $rev = '', $width=0, $height=0) {
//media to local file
if(media_isexternal($media)) {
- //check hash
- if(substr(PassHash::hmac('md5', $media, auth_cookiesalt()), 0, 6) !== $INPUT->str('hash')) {
+ //check token for external image and additional for resized and cached images
+ if(media_get_token($media, $width, $height) !== $INPUT->str('tok')) {
return array(412, 'Precondition Failed');
}
//handle external images
diff --git a/inc/html.php b/inc/html.php
index 614cf172c..a2a726406 100644
--- a/inc/html.php
+++ b/inc/html.php
@@ -575,18 +575,18 @@ function html_revisions($first=0, $media_id = false){
if ($info['sum']) {
$form->addElement(form_makeOpenTag('span', array('class' => 'sum')));
if (!$media_id) $form->addElement(' – ');
- $form->addElement(htmlspecialchars($info['sum']));
+ $form->addElement('<bdi>'.htmlspecialchars($info['sum']).'</bdi>');
$form->addElement(form_makeCloseTag('span'));
}
$form->addElement(form_makeOpenTag('span', array('class' => 'user')));
if($info['user']){
- $form->addElement(editorinfo($info['user']));
+ $form->addElement('<bdi>'.editorinfo($info['user']).'</bdi>');
if(auth_ismanager()){
- $form->addElement(' ('.$info['ip'].')');
+ $form->addElement(' <bdo dir="ltr">('.$info['ip'].')</bdo>');
}
}else{
- $form->addElement($info['ip']);
+ $form->addElement('<bdo dir="ltr">'.$info['ip'].'</bdo>');
}
$form->addElement(form_makeCloseTag('span'));
@@ -774,12 +774,12 @@ function html_recent($first=0, $show_changes='both'){
$form->addElement(form_makeOpenTag('span', array('class' => 'user')));
if($recent['user']){
- $form->addElement(editorinfo($recent['user']));
+ $form->addElement('<bdi>'.editorinfo($recent['user']).'</bdi>');
if(auth_ismanager()){
- $form->addElement(' ('.$recent['ip'].')');
+ $form->addElement(' <bdo dir="ltr">('.$recent['ip'].')</bdo>');
}
}else{
- $form->addElement($recent['ip']);
+ $form->addElement('<bdo dir="ltr">'.$recent['ip'].'</bdo>');
}
$form->addElement(form_makeCloseTag('span'));
@@ -1027,52 +1027,52 @@ function html_diff_head($l_rev, $r_rev, $id = null, $media = false, $inline = fa
}else{
$l_info = getRevisionInfo($id,$l_rev,true, $media);
if($l_info['user']){
- $l_user = editorinfo($l_info['user']);
- if(auth_ismanager()) $l_user .= ' ('.$l_info['ip'].')';
+ $l_user = '<bdi>'.editorinfo($l_info['user']).'</bdi>';
+ if(auth_ismanager()) $l_user .= ' <bdo dir="ltr">('.$l_info['ip'].')</bdo>';
} else {
- $l_user = $l_info['ip'];
+ $l_user = '<bdo dir="ltr">'.$l_info['ip'].'</bdo>';
}
$l_user = '<span class="user">'.$l_user.'</span>';
- $l_sum = ($l_info['sum']) ? '<span class="sum">'.hsc($l_info['sum']).'</span>' : '';
+ $l_sum = ($l_info['sum']) ? '<span class="sum"><bdi>'.hsc($l_info['sum']).'</bdi></span>' : '';
if ($l_info['type']===DOKU_CHANGE_TYPE_MINOR_EDIT) $l_minor = 'class="minor"';
$l_head_title = ($media) ? dformat($l_rev) : $id.' ['.dformat($l_rev).']';
- $l_head = '<a class="wikilink1" href="'.$ml_or_wl($id,"rev=$l_rev").'">'.
- $l_head_title.'</a>'.
+ $l_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($id,"rev=$l_rev").'">'.
+ $l_head_title.'</a></bdi>'.
$head_separator.$l_user.' '.$l_sum;
}
if($r_rev){
$r_info = getRevisionInfo($id,$r_rev,true, $media);
if($r_info['user']){
- $r_user = editorinfo($r_info['user']);
- if(auth_ismanager()) $r_user .= ' ('.$r_info['ip'].')';
+ $r_user = '<bdi>'.editorinfo($r_info['user']).'</bdi>';
+ if(auth_ismanager()) $r_user .= ' <bdo dir="ltr">('.$r_info['ip'].')</bdo>';
} else {
- $r_user = $r_info['ip'];
+ $r_user = '<bdo dir="ltr">'.$r_info['ip'].'</bdo>';
}
$r_user = '<span class="user">'.$r_user.'</span>';
- $r_sum = ($r_info['sum']) ? '<span class="sum">'.hsc($r_info['sum']).'</span>' : '';
+ $r_sum = ($r_info['sum']) ? '<span class="sum"><bdi>'.hsc($r_info['sum']).'</bdi></span>' : '';
if ($r_info['type']===DOKU_CHANGE_TYPE_MINOR_EDIT) $r_minor = 'class="minor"';
$r_head_title = ($media) ? dformat($r_rev) : $id.' ['.dformat($r_rev).']';
- $r_head = '<a class="wikilink1" href="'.$ml_or_wl($id,"rev=$r_rev").'">'.
- $r_head_title.'</a>'.
+ $r_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($id,"rev=$r_rev").'">'.
+ $r_head_title.'</a></bdi>'.
$head_separator.$r_user.' '.$r_sum;
}elseif($_rev = @filemtime($media_or_wikiFN($id))){
$_info = getRevisionInfo($id,$_rev,true, $media);
if($_info['user']){
- $_user = editorinfo($_info['user']);
- if(auth_ismanager()) $_user .= ' ('.$_info['ip'].')';
+ $_user = '<bdi>'.editorinfo($_info['user']).'</bdi>';
+ if(auth_ismanager()) $_user .= ' <bdo dir="ltr">('.$_info['ip'].')</bdo>';
} else {
- $_user = $_info['ip'];
+ $_user = '<bdo dir="ltr">'.$_info['ip'].'</bdo>';
}
$_user = '<span class="user">'.$_user.'</span>';
- $_sum = ($_info['sum']) ? '<span class="sum">'.hsc($_info['sum']).'</span>' : '';
+ $_sum = ($_info['sum']) ? '<span class="sum"><bdi>'.hsc($_info['sum']).'</span></bdi>' : '';
if ($_info['type']===DOKU_CHANGE_TYPE_MINOR_EDIT) $r_minor = 'class="minor"';
$r_head_title = ($media) ? dformat($_rev) : $id.' ['.dformat($_rev).']';
- $r_head = '<a class="wikilink1" href="'.$ml_or_wl($id).'">'.
- $r_head_title.'</a> '.
+ $r_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($id).'">'.
+ $r_head_title.'</a></bdi> '.
'('.$lang['current'].')'.
$head_separator.$_user.' '.$_sum;
}else{
@@ -1390,6 +1390,23 @@ function html_updateprofile(){
$form->endFieldset();
html_form('updateprofile', $form);
+
+ if ($auth->canDo('delUser') && actionOK('profile_delete')) {
+ $form_profiledelete = new Doku_Form(array('id' => 'dw__profiledelete'));
+ $form_profiledelete->startFieldset($lang['profdeleteuser']);
+ $form_profiledelete->addHidden('do', 'profile_delete');
+ $form_profiledelete->addHidden('delete', '1');
+ $form_profiledelete->addElement(form_makeCheckboxField('confirm_delete', '1', $lang['profconfdelete'],'dw__confirmdelete','', array('required' => 'required')));
+ if ($conf['profileconfirm']) {
+ $form_profiledelete->addElement(form_makeTag('br'));
+ $form_profiledelete->addElement(form_makePasswordField('oldpass', $lang['oldpass'], '', 'block', array('size'=>'50', 'required' => 'required')));
+ }
+ $form_profiledelete->addElement(form_makeButton('submit', '', $lang['btn_deleteuser']));
+ $form_profiledelete->endFieldset();
+
+ html_form('profiledelete', $form_profiledelete);
+ }
+
print '</div>'.NL;
}
@@ -1612,7 +1629,9 @@ function html_debug(){
if($auth){
print '<b>Auth backend capabilities:</b><pre>';
- print_r($auth->cando);
+ foreach ($auth->getCapabilities() as $cando){
+ print ' '.str_pad($cando,16) . ' => ' . (int)$auth->canDo($cando) . NL;
+ }
print '</pre>';
}
diff --git a/inc/lang/de-informal/lang.php b/inc/lang/de-informal/lang.php
index a8e7f45b7..4ee9a0eed 100644
--- a/inc/lang/de-informal/lang.php
+++ b/inc/lang/de-informal/lang.php
@@ -64,6 +64,7 @@ $lang['btn_revert'] = 'Wiederherstellen';
$lang['btn_register'] = 'Registrieren';
$lang['btn_apply'] = 'Übernehmen';
$lang['btn_media'] = 'Medien-Manager';
+$lang['btn_deleteuser'] = 'Benutzerprofil löschen';
$lang['loggedinas'] = 'Angemeldet als';
$lang['user'] = 'Benutzername';
$lang['pass'] = 'Passwort';
@@ -75,6 +76,7 @@ $lang['fullname'] = 'Voller Name';
$lang['email'] = 'E-Mail';
$lang['profile'] = 'Benutzerprofil';
$lang['badlogin'] = 'Benutzername oder Passwort sind falsch.';
+$lang['badpassconfirm'] = 'Das Passwort war falsch.';
$lang['minoredit'] = 'Kleine Änderung';
$lang['draftdate'] = 'Entwurf gespeichert am';
$lang['nosecedit'] = 'Diese Seite wurde in der Zwischenzeit geändert, da das Sektionsinfo veraltet ist. Die ganze Seite wird stattdessen geladen.';
@@ -91,6 +93,11 @@ $lang['profna'] = 'Änderung des Benutzerprofils in diesem Wiki n
$lang['profnochange'] = 'Keine Änderungen, nichts zu tun.';
$lang['profnoempty'] = 'Es muss ein Name oder eine E-Mail Adresse angegeben werden.';
$lang['profchanged'] = 'Benutzerprofil erfolgreich geändert.';
+$lang['profnodelete'] = 'Dieses Wiki unterstützt nicht das Löschen von Benutzern.';
+$lang['profdeleteuser'] = 'Benutzerprofil löschen';
+$lang['profdeleted'] = 'Dein Benutzerprofil wurde im Wiki gelöscht.';
+$lang['profconfdelete'] = 'Ich möchte mein Benutzerprofil löschen.<br/> Diese Aktion ist nicht umkehrbar.';
+$lang['profconfdeletemissing'] = 'Bestätigungs-Checkbox wurde nicht angehakt.';
$lang['pwdforget'] = 'Passwort vergessen? Fordere ein neues an';
$lang['resendna'] = 'Passwörter versenden ist in diesem Wiki nicht möglich.';
$lang['resendpwd'] = 'Neues Passwort setzen für';
diff --git a/inc/lang/de/lang.php b/inc/lang/de/lang.php
index b914f01aa..496eff2e5 100644
--- a/inc/lang/de/lang.php
+++ b/inc/lang/de/lang.php
@@ -65,6 +65,7 @@ $lang['btn_revert'] = 'Wiederherstellen';
$lang['btn_register'] = 'Registrieren';
$lang['btn_apply'] = 'Übernehmen';
$lang['btn_media'] = 'Medien-Manager';
+$lang['btn_deleteuser'] = 'Benutzerprofil löschen';
$lang['loggedinas'] = 'Angemeldet als';
$lang['user'] = 'Benutzername';
$lang['pass'] = 'Passwort';
@@ -76,6 +77,7 @@ $lang['fullname'] = 'Voller Name';
$lang['email'] = 'E-Mail';
$lang['profile'] = 'Benutzerprofil';
$lang['badlogin'] = 'Benutzername oder Passwort sind falsch.';
+$lang['badpassconfirm'] = 'Das Passwort war falsch.';
$lang['minoredit'] = 'kleine Änderung';
$lang['draftdate'] = 'Entwurf gespeichert am';
$lang['nosecedit'] = 'Diese Seite wurde in der Zwischenzeit geändert, Sektionsinfo ist veraltet, lade stattdessen volle Seite.';
@@ -92,6 +94,11 @@ $lang['profna'] = 'Änderung des Benutzerprofils in diesem Wiki n
$lang['profnochange'] = 'Keine Änderungen, nichts zu tun.';
$lang['profnoempty'] = 'Es muss ein Name und eine E-Mail-Adresse angegeben werden.';
$lang['profchanged'] = 'Benutzerprofil erfolgreich geändert.';
+$lang['profnodelete'] = 'Dieses Wiki unterstützt nicht das Löschen von Benutzern.';
+$lang['profdeleteuser'] = 'Benutzerprofil löschen';
+$lang['profdeleted'] = 'Ihr Benutzerprofil wurde im Wiki gelöscht.';
+$lang['profconfdelete'] = 'Ich möchte mein Benutzerprofil löschen.<br/> Diese Aktion ist nicht umkehrbar.';
+$lang['profconfdeletemissing'] = 'Bestätigungs-Checkbox wurde nicht angehakt.';
$lang['pwdforget'] = 'Passwort vergessen? Fordere ein neues an';
$lang['resendna'] = 'Passwörter versenden ist in diesem Wiki nicht möglich.';
$lang['resendpwd'] = 'Neues Passwort setzen für';
diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php
index 00e71d254..630ccb3ff 100644
--- a/inc/lang/en/lang.php
+++ b/inc/lang/en/lang.php
@@ -51,6 +51,7 @@ $lang['btn_revert'] = 'Restore';
$lang['btn_register'] = 'Register';
$lang['btn_apply'] = 'Apply';
$lang['btn_media'] = 'Media Manager';
+$lang['btn_deleteuser'] = 'Remove My Account';
$lang['loggedinas'] = 'Logged in as';
$lang['user'] = 'Username';
@@ -63,6 +64,7 @@ $lang['fullname'] = 'Real name';
$lang['email'] = 'E-Mail';
$lang['profile'] = 'User Profile';
$lang['badlogin'] = 'Sorry, username or password was wrong.';
+$lang['badpassconfirm'] = 'Sorry, the password was wrong';
$lang['minoredit'] = 'Minor Changes';
$lang['draftdate'] = 'Draft autosaved on'; // full dformat date will be added
$lang['nosecedit'] = 'The page was changed in the meantime, section info was out of date loaded full page instead.';
@@ -81,6 +83,11 @@ $lang['profna'] = 'This wiki does not support profile modificatio
$lang['profnochange'] = 'No changes, nothing to do.';
$lang['profnoempty'] = 'An empty name or email address is not allowed.';
$lang['profchanged'] = 'User profile successfully updated.';
+$lang['profnodelete'] = 'This wiki does not support deleting users';
+$lang['profdeleteuser'] = 'Delete Account';
+$lang['profdeleted'] = 'Your user account has been deleted from this wiki';
+$lang['profconfdelete'] = 'I wish to remove my account from this wiki. <br/> This action can not be undone.';
+$lang['profconfdeletemissing'] = 'Confirmation check box not ticked';
$lang['pwdforget'] = 'Forgotten your password? Get a new one';
$lang['resendna'] = 'This wiki does not support password resending.';
diff --git a/inc/lang/nl/lang.php b/inc/lang/nl/lang.php
index 6c416ca74..c45c172fb 100644
--- a/inc/lang/nl/lang.php
+++ b/inc/lang/nl/lang.php
@@ -1,8 +1,8 @@
<?php
+
/**
- * dutch language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author François Kooman <fkooman.tuxed.net>
* @author Jack van Klaren <dokuwiki@afentoe.xs4all.nl>
* @author Riny Heijdendael <riny@heijdendael.nl>
@@ -17,6 +17,7 @@
* @author Jeroen
* @author Ricardo Guijt <ricardoguijt@gmail.com>
* @author Gerrit <klapinklapin@gmail.com>
+ * @author mprins <mprins@users.sf.net>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -60,6 +61,7 @@ $lang['btn_revert'] = 'Herstellen';
$lang['btn_register'] = 'Registreren';
$lang['btn_apply'] = 'Toepassen';
$lang['btn_media'] = 'Mediabeheerder';
+$lang['btn_deleteuser'] = 'Verwijder mijn account';
$lang['loggedinas'] = 'Ingelogd als';
$lang['user'] = 'Gebruikersnaam';
$lang['pass'] = 'Wachtwoord';
@@ -71,6 +73,7 @@ $lang['fullname'] = 'Volledige naam';
$lang['email'] = 'E-mail';
$lang['profile'] = 'Gebruikersprofiel';
$lang['badlogin'] = 'Sorry, gebruikersnaam of wachtwoord onjuist';
+$lang['badpassconfirm'] = 'Sorry, het wachtwoord was onjuist';
$lang['minoredit'] = 'Kleine wijziging';
$lang['draftdate'] = 'Concept automatisch opgeslagen op';
$lang['nosecedit'] = 'De pagina is tussentijds veranderd, sectie-informatie was verouderd, volledige pagina geladen.';
@@ -87,6 +90,11 @@ $lang['profna'] = 'Deze wiki ondersteunt geen profielwijzigingen'
$lang['profnochange'] = 'Geen wijzigingen, niets gedaan';
$lang['profnoempty'] = 'Een lege gebruikersnaam of e-mailadres is niet toegestaan';
$lang['profchanged'] = 'Gebruikersprofiel succesvol aangepast';
+$lang['profnodelete'] = 'Deze wiki heeft biedt geen ondersteuning voor verwijdering van gebruikers';
+$lang['profdeleteuser'] = 'Verwijder gebruiker';
+$lang['profdeleted'] = 'Uw gebruikersaccount is verwijderd van deze wiki';
+$lang['profconfdelete'] = 'Ik wik mijn gebruikersaccount verwijderen van deze wiki. <br/> Deze actie kan niet ongedaan gemaakt worden.';
+$lang['profconfdeletemissing'] = 'Bevestigingsvinkje niet gezet';
$lang['pwdforget'] = 'Je wachtwoord vergeten? Vraag een nieuw wachtwoord aan';
$lang['resendna'] = 'Deze wiki ondersteunt het verzenden van wachtwoorden niet';
$lang['resendpwd'] = 'Nieuw wachtwoord bepalen voor';
diff --git a/inc/lang/sv/lang.php b/inc/lang/sv/lang.php
index 9608784c6..b00c61054 100644
--- a/inc/lang/sv/lang.php
+++ b/inc/lang/sv/lang.php
@@ -1,12 +1,11 @@
<?php
+
/**
- * Swedish language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Joaquim Homrighausen <joho@webbplatsen.se>
* @author Per Foreby <per@foreby.se>
* @author Nicklas Henriksson <nicklas[at]nihe.se>
- * @author Håkan Sandell <hakan.sandell[at]mydata.se>
* @author Håkan Sandell <hakan.sandell@home.se>
* @author Dennis Karlsson
* @author Tormod Otter Johansson <tormod@latast.se>
@@ -18,6 +17,7 @@
* @author Peter Åström <eaustreum@gmail.com>
* @author mikael@mallander.net
* @author Smorkster Andersson smorkster@gmail.com
+ * @author Henrik <henrik@idealis.se>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -61,6 +61,7 @@ $lang['btn_revert'] = 'Återställ';
$lang['btn_register'] = 'Registrera';
$lang['btn_apply'] = 'Verkställ';
$lang['btn_media'] = 'Media Hanteraren';
+$lang['btn_deleteuser'] = 'Ta bort Mitt Konto';
$lang['loggedinas'] = 'Inloggad som';
$lang['user'] = 'Användarnamn';
$lang['pass'] = 'Lösenord';
@@ -72,6 +73,7 @@ $lang['fullname'] = 'Namn';
$lang['email'] = 'E-post';
$lang['profile'] = 'Användarprofil';
$lang['badlogin'] = 'Felaktigt användarnamn eller lösenord.';
+$lang['badpassconfirm'] = 'Ledsen, lösenordet var felaktigt';
$lang['minoredit'] = 'Små ändringar';
$lang['draftdate'] = 'Utkast automatiskt sparat';
$lang['nosecedit'] = 'Sidan ändrades medan du skrev, sektionsinformationen var inte uppdaterad. Laddar hela sidan istället.';
@@ -88,6 +90,11 @@ $lang['profna'] = 'Denna wiki stödjer inte ändringar av profile
$lang['profnochange'] = 'Ingenting ändrades, inget att göra.';
$lang['profnoempty'] = 'Namn och e-postadress måste fyllas i.';
$lang['profchanged'] = 'Användarprofilen uppdaterad.';
+$lang['profnodelete'] = 'Den här wiki:n stödjer ej borttagning av användare';
+$lang['profdeleteuser'] = 'Radera kontot';
+$lang['profdeleted'] = 'Ditt användarkonto har raderats från den här wiki:n';
+$lang['profconfdelete'] = 'Jag vill ta bort mitt konto/inlogg på den här wiki:n <br/> Denna åtgärd går ej att ångra.';
+$lang['profconfdeletemissing'] = 'Bekräftelse-kryssrutan är ej markerad';
$lang['pwdforget'] = 'Glömt ditt lösenord? Ordna ett nytt';
$lang['resendna'] = 'Den här wikin stödjer inte utskick av lösenord.';
$lang['resendpwd'] = 'Sätt lösenord för';
@@ -310,6 +317,7 @@ $lang['media_searchtab'] = 'Sök';
$lang['media_file'] = 'Fil';
$lang['media_viewtab'] = 'Visa';
$lang['media_edittab'] = 'Redigera';
+$lang['media_historytab'] = 'Historik';
$lang['media_list_thumbs'] = 'Miniatyrbild';
$lang['media_list_rows'] = 'Rader';
$lang['media_sort_name'] = 'Namn';
@@ -321,6 +329,7 @@ $lang['media_search'] = 'Sök i %s';
$lang['media_view'] = '%s';
$lang['media_viewold'] = '%s vid %s';
$lang['media_edit'] = 'Redigera %s';
+$lang['media_history'] = '%s-historik';
$lang['media_meta_edited'] = 'metadata redigerat';
$lang['media_perm_read'] = 'Du har tyvärr inte tillräckliga behörigheter för att läsa filer.';
$lang['media_perm_upload'] = 'Du har tyvärr inte tillräckliga behörigheter för att ladda upp filer.';
diff --git a/inc/lessc.inc.php b/inc/lessc.inc.php
new file mode 100644
index 000000000..5c81ad2a9
--- /dev/null
+++ b/inc/lessc.inc.php
@@ -0,0 +1,3481 @@
+<?php
+
+/**
+ * lessphp v0.3.9
+ * http://leafo.net/lessphp
+ *
+ * LESS css compiler, adapted from http://lesscss.org
+ *
+ * Copyright 2012, Leaf Corcoran <leafot@gmail.com>
+ * Licensed under MIT or GPLv3, see LICENSE
+ */
+
+
+/**
+ * The less compiler and parser.
+ *
+ * Converting LESS to CSS is a three stage process. The incoming file is parsed
+ * by `lessc_parser` into a syntax tree, then it is compiled into another tree
+ * representing the CSS structure by `lessc`. The CSS tree is fed into a
+ * formatter, like `lessc_formatter` which then outputs CSS as a string.
+ *
+ * During the first compile, all values are *reduced*, which means that their
+ * types are brought to the lowest form before being dump as strings. This
+ * handles math equations, variable dereferences, and the like.
+ *
+ * The `parse` function of `lessc` is the entry point.
+ *
+ * In summary:
+ *
+ * The `lessc` class creates an intstance of the parser, feeds it LESS code,
+ * then transforms the resulting tree to a CSS tree. This class also holds the
+ * evaluation context, such as all available mixins and variables at any given
+ * time.
+ *
+ * The `lessc_parser` class is only concerned with parsing its input.
+ *
+ * The `lessc_formatter` takes a CSS tree, and dumps it to a formatted string,
+ * handling things like indentation.
+ */
+class lessc {
+ static public $VERSION = "v0.3.9";
+ static protected $TRUE = array("keyword", "true");
+ static protected $FALSE = array("keyword", "false");
+
+ protected $libFunctions = array();
+ protected $registeredVars = array();
+ protected $preserveComments = false;
+
+ public $vPrefix = '@'; // prefix of abstract properties
+ public $mPrefix = '$'; // prefix of abstract blocks
+ public $parentSelector = '&';
+
+ public $importDisabled = false;
+ public $importDir = '';
+
+ protected $numberPrecision = null;
+
+ // set to the parser that generated the current line when compiling
+ // so we know how to create error messages
+ protected $sourceParser = null;
+ protected $sourceLoc = null;
+
+ static public $defaultValue = array("keyword", "");
+
+ static protected $nextImportId = 0; // uniquely identify imports
+
+ // attempts to find the path of an import url, returns null for css files
+ protected function findImport($url) {
+ foreach ((array)$this->importDir as $dir) {
+ $full = $dir.(substr($dir, -1) != '/' ? '/' : '').$url;
+ if ($this->fileExists($file = $full.'.less') || $this->fileExists($file = $full)) {
+ return $file;
+ }
+ }
+
+ return null;
+ }
+
+ protected function fileExists($name) {
+ return is_file($name);
+ }
+
+ static public function compressList($items, $delim) {
+ if (!isset($items[1]) && isset($items[0])) return $items[0];
+ else return array('list', $delim, $items);
+ }
+
+ static public function preg_quote($what) {
+ return preg_quote($what, '/');
+ }
+
+ protected function tryImport($importPath, $parentBlock, $out) {
+ if ($importPath[0] == "function" && $importPath[1] == "url") {
+ $importPath = $this->flattenList($importPath[2]);
+ }
+
+ $str = $this->coerceString($importPath);
+ if ($str === null) return false;
+
+ $url = $this->compileValue($this->lib_e($str));
+
+ // don't import if it ends in css
+ if (substr_compare($url, '.css', -4, 4) === 0) return false;
+
+ $realPath = $this->findImport($url);
+ if ($realPath === null) return false;
+
+ if ($this->importDisabled) {
+ return array(false, "/* import disabled */");
+ }
+
+ $this->addParsedFile($realPath);
+ $parser = $this->makeParser($realPath);
+ $root = $parser->parse(file_get_contents($realPath));
+
+ // set the parents of all the block props
+ foreach ($root->props as $prop) {
+ if ($prop[0] == "block") {
+ $prop[1]->parent = $parentBlock;
+ }
+ }
+
+ // copy mixins into scope, set their parents
+ // bring blocks from import into current block
+ // TODO: need to mark the source parser these came from this file
+ foreach ($root->children as $childName => $child) {
+ if (isset($parentBlock->children[$childName])) {
+ $parentBlock->children[$childName] = array_merge(
+ $parentBlock->children[$childName],
+ $child);
+ } else {
+ $parentBlock->children[$childName] = $child;
+ }
+ }
+
+ $pi = pathinfo($realPath);
+ $dir = $pi["dirname"];
+
+ list($top, $bottom) = $this->sortProps($root->props, true);
+ $this->compileImportedProps($top, $parentBlock, $out, $parser, $dir);
+
+ return array(true, $bottom, $parser, $dir);
+ }
+
+ protected function compileImportedProps($props, $block, $out, $sourceParser, $importDir) {
+ $oldSourceParser = $this->sourceParser;
+
+ $oldImport = $this->importDir;
+
+ // TODO: this is because the importDir api is stupid
+ $this->importDir = (array)$this->importDir;
+ array_unshift($this->importDir, $importDir);
+
+ foreach ($props as $prop) {
+ $this->compileProp($prop, $block, $out);
+ }
+
+ $this->importDir = $oldImport;
+ $this->sourceParser = $oldSourceParser;
+ }
+
+ /**
+ * Recursively compiles a block.
+ *
+ * A block is analogous to a CSS block in most cases. A single LESS document
+ * is encapsulated in a block when parsed, but it does not have parent tags
+ * so all of it's children appear on the root level when compiled.
+ *
+ * Blocks are made up of props and children.
+ *
+ * Props are property instructions, array tuples which describe an action
+ * to be taken, eg. write a property, set a variable, mixin a block.
+ *
+ * The children of a block are just all the blocks that are defined within.
+ * This is used to look up mixins when performing a mixin.
+ *
+ * Compiling the block involves pushing a fresh environment on the stack,
+ * and iterating through the props, compiling each one.
+ *
+ * See lessc::compileProp()
+ *
+ */
+ protected function compileBlock($block) {
+ switch ($block->type) {
+ case "root":
+ $this->compileRoot($block);
+ break;
+ case null:
+ $this->compileCSSBlock($block);
+ break;
+ case "media":
+ $this->compileMedia($block);
+ break;
+ case "directive":
+ $name = "@" . $block->name;
+ if (!empty($block->value)) {
+ $name .= " " . $this->compileValue($this->reduce($block->value));
+ }
+
+ $this->compileNestedBlock($block, array($name));
+ break;
+ default:
+ $this->throwError("unknown block type: $block->type\n");
+ }
+ }
+
+ protected function compileCSSBlock($block) {
+ $env = $this->pushEnv();
+
+ $selectors = $this->compileSelectors($block->tags);
+ $env->selectors = $this->multiplySelectors($selectors);
+ $out = $this->makeOutputBlock(null, $env->selectors);
+
+ $this->scope->children[] = $out;
+ $this->compileProps($block, $out);
+
+ $block->scope = $env; // mixins carry scope with them!
+ $this->popEnv();
+ }
+
+ protected function compileMedia($media) {
+ $env = $this->pushEnv($media);
+ $parentScope = $this->mediaParent($this->scope);
+
+ $query = $this->compileMediaQuery($this->multiplyMedia($env));
+
+ $this->scope = $this->makeOutputBlock($media->type, array($query));
+ $parentScope->children[] = $this->scope;
+
+ $this->compileProps($media, $this->scope);
+
+ if (count($this->scope->lines) > 0) {
+ $orphanSelelectors = $this->findClosestSelectors();
+ if (!is_null($orphanSelelectors)) {
+ $orphan = $this->makeOutputBlock(null, $orphanSelelectors);
+ $orphan->lines = $this->scope->lines;
+ array_unshift($this->scope->children, $orphan);
+ $this->scope->lines = array();
+ }
+ }
+
+ $this->scope = $this->scope->parent;
+ $this->popEnv();
+ }
+
+ protected function mediaParent($scope) {
+ while (!empty($scope->parent)) {
+ if (!empty($scope->type) && $scope->type != "media") {
+ break;
+ }
+ $scope = $scope->parent;
+ }
+
+ return $scope;
+ }
+
+ protected function compileNestedBlock($block, $selectors) {
+ $this->pushEnv($block);
+ $this->scope = $this->makeOutputBlock($block->type, $selectors);
+ $this->scope->parent->children[] = $this->scope;
+
+ $this->compileProps($block, $this->scope);
+
+ $this->scope = $this->scope->parent;
+ $this->popEnv();
+ }
+
+ protected function compileRoot($root) {
+ $this->pushEnv();
+ $this->scope = $this->makeOutputBlock($root->type);
+ $this->compileProps($root, $this->scope);
+ $this->popEnv();
+ }
+
+ protected function compileProps($block, $out) {
+ foreach ($this->sortProps($block->props) as $prop) {
+ $this->compileProp($prop, $block, $out);
+ }
+ }
+
+ protected function sortProps($props, $split = false) {
+ $vars = array();
+ $imports = array();
+ $other = array();
+
+ foreach ($props as $prop) {
+ switch ($prop[0]) {
+ case "assign":
+ if (isset($prop[1][0]) && $prop[1][0] == $this->vPrefix) {
+ $vars[] = $prop;
+ } else {
+ $other[] = $prop;
+ }
+ break;
+ case "import":
+ $id = self::$nextImportId++;
+ $prop[] = $id;
+ $imports[] = $prop;
+ $other[] = array("import_mixin", $id);
+ break;
+ default:
+ $other[] = $prop;
+ }
+ }
+
+ if ($split) {
+ return array(array_merge($vars, $imports), $other);
+ } else {
+ return array_merge($vars, $imports, $other);
+ }
+ }
+
+ protected function compileMediaQuery($queries) {
+ $compiledQueries = array();
+ foreach ($queries as $query) {
+ $parts = array();
+ foreach ($query as $q) {
+ switch ($q[0]) {
+ case "mediaType":
+ $parts[] = implode(" ", array_slice($q, 1));
+ break;
+ case "mediaExp":
+ if (isset($q[2])) {
+ $parts[] = "($q[1]: " .
+ $this->compileValue($this->reduce($q[2])) . ")";
+ } else {
+ $parts[] = "($q[1])";
+ }
+ break;
+ case "variable":
+ $parts[] = $this->compileValue($this->reduce($q));
+ break;
+ }
+ }
+
+ if (count($parts) > 0) {
+ $compiledQueries[] = implode(" and ", $parts);
+ }
+ }
+
+ $out = "@media";
+ if (!empty($parts)) {
+ $out .= " " .
+ implode($this->formatter->selectorSeparator, $compiledQueries);
+ }
+ return $out;
+ }
+
+ protected function multiplyMedia($env, $childQueries = null) {
+ if (is_null($env) ||
+ !empty($env->block->type) && $env->block->type != "media")
+ {
+ return $childQueries;
+ }
+
+ // plain old block, skip
+ if (empty($env->block->type)) {
+ return $this->multiplyMedia($env->parent, $childQueries);
+ }
+
+ $out = array();
+ $queries = $env->block->queries;
+ if (is_null($childQueries)) {
+ $out = $queries;
+ } else {
+ foreach ($queries as $parent) {
+ foreach ($childQueries as $child) {
+ $out[] = array_merge($parent, $child);
+ }
+ }
+ }
+
+ return $this->multiplyMedia($env->parent, $out);
+ }
+
+ protected function expandParentSelectors(&$tag, $replace) {
+ $parts = explode("$&$", $tag);
+ $count = 0;
+ foreach ($parts as &$part) {
+ $part = str_replace($this->parentSelector, $replace, $part, $c);
+ $count += $c;
+ }
+ $tag = implode($this->parentSelector, $parts);
+ return $count;
+ }
+
+ protected function findClosestSelectors() {
+ $env = $this->env;
+ $selectors = null;
+ while ($env !== null) {
+ if (isset($env->selectors)) {
+ $selectors = $env->selectors;
+ break;
+ }
+ $env = $env->parent;
+ }
+
+ return $selectors;
+ }
+
+
+ // multiply $selectors against the nearest selectors in env
+ protected function multiplySelectors($selectors) {
+ // find parent selectors
+
+ $parentSelectors = $this->findClosestSelectors();
+ if (is_null($parentSelectors)) {
+ // kill parent reference in top level selector
+ foreach ($selectors as &$s) {
+ $this->expandParentSelectors($s, "");
+ }
+
+ return $selectors;
+ }
+
+ $out = array();
+ foreach ($parentSelectors as $parent) {
+ foreach ($selectors as $child) {
+ $count = $this->expandParentSelectors($child, $parent);
+
+ // don't prepend the parent tag if & was used
+ if ($count > 0) {
+ $out[] = trim($child);
+ } else {
+ $out[] = trim($parent . ' ' . $child);
+ }
+ }
+ }
+
+ return $out;
+ }
+
+ // reduces selector expressions
+ protected function compileSelectors($selectors) {
+ $out = array();
+
+ foreach ($selectors as $s) {
+ if (is_array($s)) {
+ list(, $value) = $s;
+ $out[] = trim($this->compileValue($this->reduce($value)));
+ } else {
+ $out[] = $s;
+ }
+ }
+
+ return $out;
+ }
+
+ protected function eq($left, $right) {
+ return $left == $right;
+ }
+
+ protected function patternMatch($block, $callingArgs) {
+ // match the guards if it has them
+ // any one of the groups must have all its guards pass for a match
+ if (!empty($block->guards)) {
+ $groupPassed = false;
+ foreach ($block->guards as $guardGroup) {
+ foreach ($guardGroup as $guard) {
+ $this->pushEnv();
+ $this->zipSetArgs($block->args, $callingArgs);
+
+ $negate = false;
+ if ($guard[0] == "negate") {
+ $guard = $guard[1];
+ $negate = true;
+ }
+
+ $passed = $this->reduce($guard) == self::$TRUE;
+ if ($negate) $passed = !$passed;
+
+ $this->popEnv();
+
+ if ($passed) {
+ $groupPassed = true;
+ } else {
+ $groupPassed = false;
+ break;
+ }
+ }
+
+ if ($groupPassed) break;
+ }
+
+ if (!$groupPassed) {
+ return false;
+ }
+ }
+
+ $numCalling = count($callingArgs);
+
+ if (empty($block->args)) {
+ return $block->isVararg || $numCalling == 0;
+ }
+
+ $i = -1; // no args
+ // try to match by arity or by argument literal
+ foreach ($block->args as $i => $arg) {
+ switch ($arg[0]) {
+ case "lit":
+ if (empty($callingArgs[$i]) || !$this->eq($arg[1], $callingArgs[$i])) {
+ return false;
+ }
+ break;
+ case "arg":
+ // no arg and no default value
+ if (!isset($callingArgs[$i]) && !isset($arg[2])) {
+ return false;
+ }
+ break;
+ case "rest":
+ $i--; // rest can be empty
+ break 2;
+ }
+ }
+
+ if ($block->isVararg) {
+ return true; // not having enough is handled above
+ } else {
+ $numMatched = $i + 1;
+ // greater than becuase default values always match
+ return $numMatched >= $numCalling;
+ }
+ }
+
+ protected function patternMatchAll($blocks, $callingArgs) {
+ $matches = null;
+ foreach ($blocks as $block) {
+ if ($this->patternMatch($block, $callingArgs)) {
+ $matches[] = $block;
+ }
+ }
+
+ return $matches;
+ }
+
+ // attempt to find blocks matched by path and args
+ protected function findBlocks($searchIn, $path, $args, $seen=array()) {
+ if ($searchIn == null) return null;
+ if (isset($seen[$searchIn->id])) return null;
+ $seen[$searchIn->id] = true;
+
+ $name = $path[0];
+
+ if (isset($searchIn->children[$name])) {
+ $blocks = $searchIn->children[$name];
+ if (count($path) == 1) {
+ $matches = $this->patternMatchAll($blocks, $args);
+ if (!empty($matches)) {
+ // This will return all blocks that match in the closest
+ // scope that has any matching block, like lessjs
+ return $matches;
+ }
+ } else {
+ $matches = array();
+ foreach ($blocks as $subBlock) {
+ $subMatches = $this->findBlocks($subBlock,
+ array_slice($path, 1), $args, $seen);
+
+ if (!is_null($subMatches)) {
+ foreach ($subMatches as $sm) {
+ $matches[] = $sm;
+ }
+ }
+ }
+
+ return count($matches) > 0 ? $matches : null;
+ }
+ }
+
+ if ($searchIn->parent === $searchIn) return null;
+ return $this->findBlocks($searchIn->parent, $path, $args, $seen);
+ }
+
+ // sets all argument names in $args to either the default value
+ // or the one passed in through $values
+ protected function zipSetArgs($args, $values) {
+ $i = 0;
+ $assignedValues = array();
+ foreach ($args as $a) {
+ if ($a[0] == "arg") {
+ if ($i < count($values) && !is_null($values[$i])) {
+ $value = $values[$i];
+ } elseif (isset($a[2])) {
+ $value = $a[2];
+ } else $value = null;
+
+ $value = $this->reduce($value);
+ $this->set($a[1], $value);
+ $assignedValues[] = $value;
+ }
+ $i++;
+ }
+
+ // check for a rest
+ $last = end($args);
+ if ($last[0] == "rest") {
+ $rest = array_slice($values, count($args) - 1);
+ $this->set($last[1], $this->reduce(array("list", " ", $rest)));
+ }
+
+ $this->env->arguments = $assignedValues;
+ }
+
+ // compile a prop and update $lines or $blocks appropriately
+ protected function compileProp($prop, $block, $out) {
+ // set error position context
+ $this->sourceLoc = isset($prop[-1]) ? $prop[-1] : -1;
+
+ switch ($prop[0]) {
+ case 'assign':
+ list(, $name, $value) = $prop;
+ if ($name[0] == $this->vPrefix) {
+ $this->set($name, $value);
+ } else {
+ $out->lines[] = $this->formatter->property($name,
+ $this->compileValue($this->reduce($value)));
+ }
+ break;
+ case 'block':
+ list(, $child) = $prop;
+ $this->compileBlock($child);
+ break;
+ case 'mixin':
+ list(, $path, $args, $suffix) = $prop;
+
+ $args = array_map(array($this, "reduce"), (array)$args);
+ $mixins = $this->findBlocks($block, $path, $args);
+
+ if ($mixins === null) {
+ // fwrite(STDERR,"failed to find block: ".implode(" > ", $path)."\n");
+ break; // throw error here??
+ }
+
+ foreach ($mixins as $mixin) {
+ if ($mixin === $block && !$args) {
+ continue;
+ }
+
+ $haveScope = false;
+ if (isset($mixin->parent->scope)) {
+ $haveScope = true;
+ $mixinParentEnv = $this->pushEnv();
+ $mixinParentEnv->storeParent = $mixin->parent->scope;
+ }
+
+ $haveArgs = false;
+ if (isset($mixin->args)) {
+ $haveArgs = true;
+ $this->pushEnv();
+ $this->zipSetArgs($mixin->args, $args);
+ }
+
+ $oldParent = $mixin->parent;
+ if ($mixin != $block) $mixin->parent = $block;
+
+ foreach ($this->sortProps($mixin->props) as $subProp) {
+ if ($suffix !== null &&
+ $subProp[0] == "assign" &&
+ is_string($subProp[1]) &&
+ $subProp[1]{0} != $this->vPrefix)
+ {
+ $subProp[2] = array(
+ 'list', ' ',
+ array($subProp[2], array('keyword', $suffix))
+ );
+ }
+
+ $this->compileProp($subProp, $mixin, $out);
+ }
+
+ $mixin->parent = $oldParent;
+
+ if ($haveArgs) $this->popEnv();
+ if ($haveScope) $this->popEnv();
+ }
+
+ break;
+ case 'raw':
+ $out->lines[] = $prop[1];
+ break;
+ case "directive":
+ list(, $name, $value) = $prop;
+ $out->lines[] = "@$name " . $this->compileValue($this->reduce($value)).';';
+ break;
+ case "comment":
+ $out->lines[] = $prop[1];
+ break;
+ case "import";
+ list(, $importPath, $importId) = $prop;
+ $importPath = $this->reduce($importPath);
+
+ if (!isset($this->env->imports)) {
+ $this->env->imports = array();
+ }
+
+ $result = $this->tryImport($importPath, $block, $out);
+
+ $this->env->imports[$importId] = $result === false ?
+ array(false, "@import " . $this->compileValue($importPath).";") :
+ $result;
+
+ break;
+ case "import_mixin":
+ list(,$importId) = $prop;
+ $import = $this->env->imports[$importId];
+ if ($import[0] === false) {
+ $out->lines[] = $import[1];
+ } else {
+ list(, $bottom, $parser, $importDir) = $import;
+ $this->compileImportedProps($bottom, $block, $out, $parser, $importDir);
+ }
+
+ break;
+ default:
+ $this->throwError("unknown op: {$prop[0]}\n");
+ }
+ }
+
+
+ /**
+ * Compiles a primitive value into a CSS property value.
+ *
+ * Values in lessphp are typed by being wrapped in arrays, their format is
+ * typically:
+ *
+ * array(type, contents [, additional_contents]*)
+ *
+ * The input is expected to be reduced. This function will not work on
+ * things like expressions and variables.
+ */
+ protected function compileValue($value) {
+ switch ($value[0]) {
+ case 'list':
+ // [1] - delimiter
+ // [2] - array of values
+ return implode($value[1], array_map(array($this, 'compileValue'), $value[2]));
+ case 'raw_color':
+ if (!empty($this->formatter->compressColors)) {
+ return $this->compileValue($this->coerceColor($value));
+ }
+ return $value[1];
+ case 'keyword':
+ // [1] - the keyword
+ return $value[1];
+ case 'number':
+ list(, $num, $unit) = $value;
+ // [1] - the number
+ // [2] - the unit
+ if ($this->numberPrecision !== null) {
+ $num = round($num, $this->numberPrecision);
+ }
+ return $num . $unit;
+ case 'string':
+ // [1] - contents of string (includes quotes)
+ list(, $delim, $content) = $value;
+ foreach ($content as &$part) {
+ if (is_array($part)) {
+ $part = $this->compileValue($part);
+ }
+ }
+ return $delim . implode($content) . $delim;
+ case 'color':
+ // [1] - red component (either number or a %)
+ // [2] - green component
+ // [3] - blue component
+ // [4] - optional alpha component
+ list(, $r, $g, $b) = $value;
+ $r = round($r);
+ $g = round($g);
+ $b = round($b);
+
+ if (count($value) == 5 && $value[4] != 1) { // rgba
+ return 'rgba('.$r.','.$g.','.$b.','.$value[4].')';
+ }
+
+ $h = sprintf("#%02x%02x%02x", $r, $g, $b);
+
+ if (!empty($this->formatter->compressColors)) {
+ // Converting hex color to short notation (e.g. #003399 to #039)
+ if ($h[1] === $h[2] && $h[3] === $h[4] && $h[5] === $h[6]) {
+ $h = '#' . $h[1] . $h[3] . $h[5];
+ }
+ }
+
+ return $h;
+
+ case 'function':
+ list(, $name, $args) = $value;
+ return $name.'('.$this->compileValue($args).')';
+ default: // assumed to be unit
+ $this->throwError("unknown value type: $value[0]");
+ }
+ }
+
+ protected function lib_isnumber($value) {
+ return $this->toBool($value[0] == "number");
+ }
+
+ protected function lib_isstring($value) {
+ return $this->toBool($value[0] == "string");
+ }
+
+ protected function lib_iscolor($value) {
+ return $this->toBool($this->coerceColor($value));
+ }
+
+ protected function lib_iskeyword($value) {
+ return $this->toBool($value[0] == "keyword");
+ }
+
+ protected function lib_ispixel($value) {
+ return $this->toBool($value[0] == "number" && $value[2] == "px");
+ }
+
+ protected function lib_ispercentage($value) {
+ return $this->toBool($value[0] == "number" && $value[2] == "%");
+ }
+
+ protected function lib_isem($value) {
+ return $this->toBool($value[0] == "number" && $value[2] == "em");
+ }
+
+ protected function lib_isrem($value) {
+ return $this->toBool($value[0] == "number" && $value[2] == "rem");
+ }
+
+ protected function lib_rgbahex($color) {
+ $color = $this->coerceColor($color);
+ if (is_null($color))
+ $this->throwError("color expected for rgbahex");
+
+ return sprintf("#%02x%02x%02x%02x",
+ isset($color[4]) ? $color[4]*255 : 255,
+ $color[1],$color[2], $color[3]);
+ }
+
+ protected function lib_argb($color){
+ return $this->lib_rgbahex($color);
+ }
+
+ // utility func to unquote a string
+ protected function lib_e($arg) {
+ switch ($arg[0]) {
+ case "list":
+ $items = $arg[2];
+ if (isset($items[0])) {
+ return $this->lib_e($items[0]);
+ }
+ return self::$defaultValue;
+ case "string":
+ $arg[1] = "";
+ return $arg;
+ case "keyword":
+ return $arg;
+ default:
+ return array("keyword", $this->compileValue($arg));
+ }
+ }
+
+ protected function lib__sprintf($args) {
+ if ($args[0] != "list") return $args;
+ $values = $args[2];
+ $string = array_shift($values);
+ $template = $this->compileValue($this->lib_e($string));
+
+ $i = 0;
+ if (preg_match_all('/%[dsa]/', $template, $m)) {
+ foreach ($m[0] as $match) {
+ $val = isset($values[$i]) ?
+ $this->reduce($values[$i]) : array('keyword', '');
+
+ // lessjs compat, renders fully expanded color, not raw color
+ if ($color = $this->coerceColor($val)) {
+ $val = $color;
+ }
+
+ $i++;
+ $rep = $this->compileValue($this->lib_e($val));
+ $template = preg_replace('/'.self::preg_quote($match).'/',
+ $rep, $template, 1);
+ }
+ }
+
+ $d = $string[0] == "string" ? $string[1] : '"';
+ return array("string", $d, array($template));
+ }
+
+ protected function lib_floor($arg) {
+ $value = $this->assertNumber($arg);
+ return array("number", floor($value), $arg[2]);
+ }
+
+ protected function lib_ceil($arg) {
+ $value = $this->assertNumber($arg);
+ return array("number", ceil($value), $arg[2]);
+ }
+
+ protected function lib_round($arg) {
+ $value = $this->assertNumber($arg);
+ return array("number", round($value), $arg[2]);
+ }
+
+ protected function lib_unit($arg) {
+ if ($arg[0] == "list") {
+ list($number, $newUnit) = $arg[2];
+ return array("number", $this->assertNumber($number),
+ $this->compileValue($this->lib_e($newUnit)));
+ } else {
+ return array("number", $this->assertNumber($arg), "");
+ }
+ }
+
+ /**
+ * Helper function to get arguments for color manipulation functions.
+ * takes a list that contains a color like thing and a percentage
+ */
+ protected function colorArgs($args) {
+ if ($args[0] != 'list' || count($args[2]) < 2) {
+ return array(array('color', 0, 0, 0), 0);
+ }
+ list($color, $delta) = $args[2];
+ $color = $this->assertColor($color);
+ $delta = floatval($delta[1]);
+
+ return array($color, $delta);
+ }
+
+ protected function lib_darken($args) {
+ list($color, $delta) = $this->colorArgs($args);
+
+ $hsl = $this->toHSL($color);
+ $hsl[3] = $this->clamp($hsl[3] - $delta, 100);
+ return $this->toRGB($hsl);
+ }
+
+ protected function lib_lighten($args) {
+ list($color, $delta) = $this->colorArgs($args);
+
+ $hsl = $this->toHSL($color);
+ $hsl[3] = $this->clamp($hsl[3] + $delta, 100);
+ return $this->toRGB($hsl);
+ }
+
+ protected function lib_saturate($args) {
+ list($color, $delta) = $this->colorArgs($args);
+
+ $hsl = $this->toHSL($color);
+ $hsl[2] = $this->clamp($hsl[2] + $delta, 100);
+ return $this->toRGB($hsl);
+ }
+
+ protected function lib_desaturate($args) {
+ list($color, $delta) = $this->colorArgs($args);
+
+ $hsl = $this->toHSL($color);
+ $hsl[2] = $this->clamp($hsl[2] - $delta, 100);
+ return $this->toRGB($hsl);
+ }
+
+ protected function lib_spin($args) {
+ list($color, $delta) = $this->colorArgs($args);
+
+ $hsl = $this->toHSL($color);
+
+ $hsl[1] = $hsl[1] + $delta % 360;
+ if ($hsl[1] < 0) $hsl[1] += 360;
+
+ return $this->toRGB($hsl);
+ }
+
+ protected function lib_fadeout($args) {
+ list($color, $delta) = $this->colorArgs($args);
+ $color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) - $delta/100);
+ return $color;
+ }
+
+ protected function lib_fadein($args) {
+ list($color, $delta) = $this->colorArgs($args);
+ $color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) + $delta/100);
+ return $color;
+ }
+
+ protected function lib_hue($color) {
+ $hsl = $this->toHSL($this->assertColor($color));
+ return round($hsl[1]);
+ }
+
+ protected function lib_saturation($color) {
+ $hsl = $this->toHSL($this->assertColor($color));
+ return round($hsl[2]);
+ }
+
+ protected function lib_lightness($color) {
+ $hsl = $this->toHSL($this->assertColor($color));
+ return round($hsl[3]);
+ }
+
+ // get the alpha of a color
+ // defaults to 1 for non-colors or colors without an alpha
+ protected function lib_alpha($value) {
+ if (!is_null($color = $this->coerceColor($value))) {
+ return isset($color[4]) ? $color[4] : 1;
+ }
+ }
+
+ // set the alpha of the color
+ protected function lib_fade($args) {
+ list($color, $alpha) = $this->colorArgs($args);
+ $color[4] = $this->clamp($alpha / 100.0);
+ return $color;
+ }
+
+ protected function lib_percentage($arg) {
+ $num = $this->assertNumber($arg);
+ return array("number", $num*100, "%");
+ }
+
+ // mixes two colors by weight
+ // mix(@color1, @color2, [@weight: 50%]);
+ // http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#mix-instance_method
+ protected function lib_mix($args) {
+ if ($args[0] != "list" || count($args[2]) < 2)
+ $this->throwError("mix expects (color1, color2, weight)");
+
+ list($first, $second) = $args[2];
+ $first = $this->assertColor($first);
+ $second = $this->assertColor($second);
+
+ $first_a = $this->lib_alpha($first);
+ $second_a = $this->lib_alpha($second);
+
+ if (isset($args[2][2])) {
+ $weight = $args[2][2][1] / 100.0;
+ } else {
+ $weight = 0.5;
+ }
+
+ $w = $weight * 2 - 1;
+ $a = $first_a - $second_a;
+
+ $w1 = (($w * $a == -1 ? $w : ($w + $a)/(1 + $w * $a)) + 1) / 2.0;
+ $w2 = 1.0 - $w1;
+
+ $new = array('color',
+ $w1 * $first[1] + $w2 * $second[1],
+ $w1 * $first[2] + $w2 * $second[2],
+ $w1 * $first[3] + $w2 * $second[3],
+ );
+
+ if ($first_a != 1.0 || $second_a != 1.0) {
+ $new[] = $first_a * $weight + $second_a * ($weight - 1);
+ }
+
+ return $this->fixColor($new);
+ }
+
+ protected function lib_contrast($args) {
+ if ($args[0] != 'list' || count($args[2]) < 3) {
+ return array(array('color', 0, 0, 0), 0);
+ }
+
+ list($inputColor, $darkColor, $lightColor) = $args[2];
+
+ $inputColor = $this->assertColor($inputColor);
+ $darkColor = $this->assertColor($darkColor);
+ $lightColor = $this->assertColor($lightColor);
+ $hsl = $this->toHSL($inputColor);
+
+ if ($hsl[3] > 50) {
+ return $darkColor;
+ }
+
+ return $lightColor;
+ }
+
+ protected function assertColor($value, $error = "expected color value") {
+ $color = $this->coerceColor($value);
+ if (is_null($color)) $this->throwError($error);
+ return $color;
+ }
+
+ protected function assertNumber($value, $error = "expecting number") {
+ if ($value[0] == "number") return $value[1];
+ $this->throwError($error);
+ }
+
+ protected function toHSL($color) {
+ if ($color[0] == 'hsl') return $color;
+
+ $r = $color[1] / 255;
+ $g = $color[2] / 255;
+ $b = $color[3] / 255;
+
+ $min = min($r, $g, $b);
+ $max = max($r, $g, $b);
+
+ $L = ($min + $max) / 2;
+ if ($min == $max) {
+ $S = $H = 0;
+ } else {
+ if ($L < 0.5)
+ $S = ($max - $min)/($max + $min);
+ else
+ $S = ($max - $min)/(2.0 - $max - $min);
+
+ if ($r == $max) $H = ($g - $b)/($max - $min);
+ elseif ($g == $max) $H = 2.0 + ($b - $r)/($max - $min);
+ elseif ($b == $max) $H = 4.0 + ($r - $g)/($max - $min);
+
+ }
+
+ $out = array('hsl',
+ ($H < 0 ? $H + 6 : $H)*60,
+ $S*100,
+ $L*100,
+ );
+
+ if (count($color) > 4) $out[] = $color[4]; // copy alpha
+ return $out;
+ }
+
+ protected function toRGB_helper($comp, $temp1, $temp2) {
+ if ($comp < 0) $comp += 1.0;
+ elseif ($comp > 1) $comp -= 1.0;
+
+ if (6 * $comp < 1) return $temp1 + ($temp2 - $temp1) * 6 * $comp;
+ if (2 * $comp < 1) return $temp2;
+ if (3 * $comp < 2) return $temp1 + ($temp2 - $temp1)*((2/3) - $comp) * 6;
+
+ return $temp1;
+ }
+
+ /**
+ * Converts a hsl array into a color value in rgb.
+ * Expects H to be in range of 0 to 360, S and L in 0 to 100
+ */
+ protected function toRGB($color) {
+ if ($color[0] == 'color') return $color;
+
+ $H = $color[1] / 360;
+ $S = $color[2] / 100;
+ $L = $color[3] / 100;
+
+ if ($S == 0) {
+ $r = $g = $b = $L;
+ } else {
+ $temp2 = $L < 0.5 ?
+ $L*(1.0 + $S) :
+ $L + $S - $L * $S;
+
+ $temp1 = 2.0 * $L - $temp2;
+
+ $r = $this->toRGB_helper($H + 1/3, $temp1, $temp2);
+ $g = $this->toRGB_helper($H, $temp1, $temp2);
+ $b = $this->toRGB_helper($H - 1/3, $temp1, $temp2);
+ }
+
+ // $out = array('color', round($r*255), round($g*255), round($b*255));
+ $out = array('color', $r*255, $g*255, $b*255);
+ if (count($color) > 4) $out[] = $color[4]; // copy alpha
+ return $out;
+ }
+
+ protected function clamp($v, $max = 1, $min = 0) {
+ return min($max, max($min, $v));
+ }
+
+ /**
+ * Convert the rgb, rgba, hsl color literals of function type
+ * as returned by the parser into values of color type.
+ */
+ protected function funcToColor($func) {
+ $fname = $func[1];
+ if ($func[2][0] != 'list') return false; // need a list of arguments
+ $rawComponents = $func[2][2];
+
+ if ($fname == 'hsl' || $fname == 'hsla') {
+ $hsl = array('hsl');
+ $i = 0;
+ foreach ($rawComponents as $c) {
+ $val = $this->reduce($c);
+ $val = isset($val[1]) ? floatval($val[1]) : 0;
+
+ if ($i == 0) $clamp = 360;
+ elseif ($i < 3) $clamp = 100;
+ else $clamp = 1;
+
+ $hsl[] = $this->clamp($val, $clamp);
+ $i++;
+ }
+
+ while (count($hsl) < 4) $hsl[] = 0;
+ return $this->toRGB($hsl);
+
+ } elseif ($fname == 'rgb' || $fname == 'rgba') {
+ $components = array();
+ $i = 1;
+ foreach ($rawComponents as $c) {
+ $c = $this->reduce($c);
+ if ($i < 4) {
+ if ($c[0] == "number" && $c[2] == "%") {
+ $components[] = 255 * ($c[1] / 100);
+ } else {
+ $components[] = floatval($c[1]);
+ }
+ } elseif ($i == 4) {
+ if ($c[0] == "number" && $c[2] == "%") {
+ $components[] = 1.0 * ($c[1] / 100);
+ } else {
+ $components[] = floatval($c[1]);
+ }
+ } else break;
+
+ $i++;
+ }
+ while (count($components) < 3) $components[] = 0;
+ array_unshift($components, 'color');
+ return $this->fixColor($components);
+ }
+
+ return false;
+ }
+
+ protected function reduce($value, $forExpression = false) {
+ switch ($value[0]) {
+ case "interpolate":
+ $reduced = $this->reduce($value[1]);
+ $var = $this->compileValue($reduced);
+ $res = $this->reduce(array("variable", $this->vPrefix . $var));
+
+ if (empty($value[2])) $res = $this->lib_e($res);
+
+ return $res;
+ case "variable":
+ $key = $value[1];
+ if (is_array($key)) {
+ $key = $this->reduce($key);
+ $key = $this->vPrefix . $this->compileValue($this->lib_e($key));
+ }
+
+ $seen =& $this->env->seenNames;
+
+ if (!empty($seen[$key])) {
+ $this->throwError("infinite loop detected: $key");
+ }
+
+ $seen[$key] = true;
+ $out = $this->reduce($this->get($key, self::$defaultValue));
+ $seen[$key] = false;
+ return $out;
+ case "list":
+ foreach ($value[2] as &$item) {
+ $item = $this->reduce($item, $forExpression);
+ }
+ return $value;
+ case "expression":
+ return $this->evaluate($value);
+ case "string":
+ foreach ($value[2] as &$part) {
+ if (is_array($part)) {
+ $strip = $part[0] == "variable";
+ $part = $this->reduce($part);
+ if ($strip) $part = $this->lib_e($part);
+ }
+ }
+ return $value;
+ case "escape":
+ list(,$inner) = $value;
+ return $this->lib_e($this->reduce($inner));
+ case "function":
+ $color = $this->funcToColor($value);
+ if ($color) return $color;
+
+ list(, $name, $args) = $value;
+ if ($name == "%") $name = "_sprintf";
+ $f = isset($this->libFunctions[$name]) ?
+ $this->libFunctions[$name] : array($this, 'lib_'.$name);
+
+ if (is_callable($f)) {
+ if ($args[0] == 'list')
+ $args = self::compressList($args[2], $args[1]);
+
+ $ret = call_user_func($f, $this->reduce($args, true), $this);
+
+ if (is_null($ret)) {
+ return array("string", "", array(
+ $name, "(", $args, ")"
+ ));
+ }
+
+ // convert to a typed value if the result is a php primitive
+ if (is_numeric($ret)) $ret = array('number', $ret, "");
+ elseif (!is_array($ret)) $ret = array('keyword', $ret);
+
+ return $ret;
+ }
+
+ // plain function, reduce args
+ $value[2] = $this->reduce($value[2]);
+ return $value;
+ case "unary":
+ list(, $op, $exp) = $value;
+ $exp = $this->reduce($exp);
+
+ if ($exp[0] == "number") {
+ switch ($op) {
+ case "+":
+ return $exp;
+ case "-":
+ $exp[1] *= -1;
+ return $exp;
+ }
+ }
+ return array("string", "", array($op, $exp));
+ }
+
+ if ($forExpression) {
+ switch ($value[0]) {
+ case "keyword":
+ if ($color = $this->coerceColor($value)) {
+ return $color;
+ }
+ break;
+ case "raw_color":
+ return $this->coerceColor($value);
+ }
+ }
+
+ return $value;
+ }
+
+
+ // coerce a value for use in color operation
+ protected function coerceColor($value) {
+ switch($value[0]) {
+ case 'color': return $value;
+ case 'raw_color':
+ $c = array("color", 0, 0, 0);
+ $colorStr = substr($value[1], 1);
+ $num = hexdec($colorStr);
+ $width = strlen($colorStr) == 3 ? 16 : 256;
+
+ for ($i = 3; $i > 0; $i--) { // 3 2 1
+ $t = $num % $width;
+ $num /= $width;
+
+ $c[$i] = $t * (256/$width) + $t * floor(16/$width);
+ }
+
+ return $c;
+ case 'keyword':
+ $name = $value[1];
+ if (isset(self::$cssColors[$name])) {
+ $rgba = explode(',', self::$cssColors[$name]);
+
+ if(isset($rgba[3]))
+ return array('color', $rgba[0], $rgba[1], $rgba[2], $rgba[3]);
+
+ return array('color', $rgba[0], $rgba[1], $rgba[2]);
+ }
+ return null;
+ }
+ }
+
+ // make something string like into a string
+ protected function coerceString($value) {
+ switch ($value[0]) {
+ case "string":
+ return $value;
+ case "keyword":
+ return array("string", "", array($value[1]));
+ }
+ return null;
+ }
+
+ // turn list of length 1 into value type
+ protected function flattenList($value) {
+ if ($value[0] == "list" && count($value[2]) == 1) {
+ return $this->flattenList($value[2][0]);
+ }
+ return $value;
+ }
+
+ protected function toBool($a) {
+ if ($a) return self::$TRUE;
+ else return self::$FALSE;
+ }
+
+ // evaluate an expression
+ protected function evaluate($exp) {
+ list(, $op, $left, $right, $whiteBefore, $whiteAfter) = $exp;
+
+ $left = $this->reduce($left, true);
+ $right = $this->reduce($right, true);
+
+ if ($leftColor = $this->coerceColor($left)) {
+ $left = $leftColor;
+ }
+
+ if ($rightColor = $this->coerceColor($right)) {
+ $right = $rightColor;
+ }
+
+ $ltype = $left[0];
+ $rtype = $right[0];
+
+ // operators that work on all types
+ if ($op == "and") {
+ return $this->toBool($left == self::$TRUE && $right == self::$TRUE);
+ }
+
+ if ($op == "=") {
+ return $this->toBool($this->eq($left, $right) );
+ }
+
+ if ($op == "+" && !is_null($str = $this->stringConcatenate($left, $right))) {
+ return $str;
+ }
+
+ // type based operators
+ $fname = "op_${ltype}_${rtype}";
+ if (is_callable(array($this, $fname))) {
+ $out = $this->$fname($op, $left, $right);
+ if (!is_null($out)) return $out;
+ }
+
+ // make the expression look it did before being parsed
+ $paddedOp = $op;
+ if ($whiteBefore) $paddedOp = " " . $paddedOp;
+ if ($whiteAfter) $paddedOp .= " ";
+
+ return array("string", "", array($left, $paddedOp, $right));
+ }
+
+ protected function stringConcatenate($left, $right) {
+ if ($strLeft = $this->coerceString($left)) {
+ if ($right[0] == "string") {
+ $right[1] = "";
+ }
+ $strLeft[2][] = $right;
+ return $strLeft;
+ }
+
+ if ($strRight = $this->coerceString($right)) {
+ array_unshift($strRight[2], $left);
+ return $strRight;
+ }
+ }
+
+
+ // make sure a color's components don't go out of bounds
+ protected function fixColor($c) {
+ foreach (range(1, 3) as $i) {
+ if ($c[$i] < 0) $c[$i] = 0;
+ if ($c[$i] > 255) $c[$i] = 255;
+ }
+
+ return $c;
+ }
+
+ protected function op_number_color($op, $lft, $rgt) {
+ if ($op == '+' || $op == '*') {
+ return $this->op_color_number($op, $rgt, $lft);
+ }
+ }
+
+ protected function op_color_number($op, $lft, $rgt) {
+ if ($rgt[0] == '%') $rgt[1] /= 100;
+
+ return $this->op_color_color($op, $lft,
+ array_fill(1, count($lft) - 1, $rgt[1]));
+ }
+
+ protected function op_color_color($op, $left, $right) {
+ $out = array('color');
+ $max = count($left) > count($right) ? count($left) : count($right);
+ foreach (range(1, $max - 1) as $i) {
+ $lval = isset($left[$i]) ? $left[$i] : 0;
+ $rval = isset($right[$i]) ? $right[$i] : 0;
+ switch ($op) {
+ case '+':
+ $out[] = $lval + $rval;
+ break;
+ case '-':
+ $out[] = $lval - $rval;
+ break;
+ case '*':
+ $out[] = $lval * $rval;
+ break;
+ case '%':
+ $out[] = $lval % $rval;
+ break;
+ case '/':
+ if ($rval == 0) $this->throwError("evaluate error: can't divide by zero");
+ $out[] = $lval / $rval;
+ break;
+ default:
+ $this->throwError('evaluate error: color op number failed on op '.$op);
+ }
+ }
+ return $this->fixColor($out);
+ }
+
+ function lib_red($color){
+ $color = $this->coerceColor($color);
+ if (is_null($color)) {
+ $this->throwError('color expected for red()');
+ }
+
+ return $color[1];
+ }
+
+ function lib_green($color){
+ $color = $this->coerceColor($color);
+ if (is_null($color)) {
+ $this->throwError('color expected for green()');
+ }
+
+ return $color[2];
+ }
+
+ function lib_blue($color){
+ $color = $this->coerceColor($color);
+ if (is_null($color)) {
+ $this->throwError('color expected for blue()');
+ }
+
+ return $color[3];
+ }
+
+
+ // operator on two numbers
+ protected function op_number_number($op, $left, $right) {
+ $unit = empty($left[2]) ? $right[2] : $left[2];
+
+ $value = 0;
+ switch ($op) {
+ case '+':
+ $value = $left[1] + $right[1];
+ break;
+ case '*':
+ $value = $left[1] * $right[1];
+ break;
+ case '-':
+ $value = $left[1] - $right[1];
+ break;
+ case '%':
+ $value = $left[1] % $right[1];
+ break;
+ case '/':
+ if ($right[1] == 0) $this->throwError('parse error: divide by zero');
+ $value = $left[1] / $right[1];
+ break;
+ case '<':
+ return $this->toBool($left[1] < $right[1]);
+ case '>':
+ return $this->toBool($left[1] > $right[1]);
+ case '>=':
+ return $this->toBool($left[1] >= $right[1]);
+ case '=<':
+ return $this->toBool($left[1] <= $right[1]);
+ default:
+ $this->throwError('parse error: unknown number operator: '.$op);
+ }
+
+ return array("number", $value, $unit);
+ }
+
+
+ /* environment functions */
+
+ protected function makeOutputBlock($type, $selectors = null) {
+ $b = new stdclass;
+ $b->lines = array();
+ $b->children = array();
+ $b->selectors = $selectors;
+ $b->type = $type;
+ $b->parent = $this->scope;
+ return $b;
+ }
+
+ // the state of execution
+ protected function pushEnv($block = null) {
+ $e = new stdclass;
+ $e->parent = $this->env;
+ $e->store = array();
+ $e->block = $block;
+
+ $this->env = $e;
+ return $e;
+ }
+
+ // pop something off the stack
+ protected function popEnv() {
+ $old = $this->env;
+ $this->env = $this->env->parent;
+ return $old;
+ }
+
+ // set something in the current env
+ protected function set($name, $value) {
+ $this->env->store[$name] = $value;
+ }
+
+
+ // get the highest occurrence entry for a name
+ protected function get($name, $default=null) {
+ $current = $this->env;
+
+ $isArguments = $name == $this->vPrefix . 'arguments';
+ while ($current) {
+ if ($isArguments && isset($current->arguments)) {
+ return array('list', ' ', $current->arguments);
+ }
+
+ if (isset($current->store[$name]))
+ return $current->store[$name];
+ else {
+ $current = isset($current->storeParent) ?
+ $current->storeParent : $current->parent;
+ }
+ }
+
+ return $default;
+ }
+
+ // inject array of unparsed strings into environment as variables
+ protected function injectVariables($args) {
+ $this->pushEnv();
+ $parser = new lessc_parser($this, __METHOD__);
+ foreach ($args as $name => $strValue) {
+ if ($name{0} != '@') $name = '@'.$name;
+ $parser->count = 0;
+ $parser->buffer = (string)$strValue;
+ if (!$parser->propertyValue($value)) {
+ throw new Exception("failed to parse passed in variable $name: $strValue");
+ }
+
+ $this->set($name, $value);
+ }
+ }
+
+ /**
+ * Initialize any static state, can initialize parser for a file
+ * $opts isn't used yet
+ */
+ public function __construct($fname = null) {
+ if ($fname !== null) {
+ // used for deprecated parse method
+ $this->_parseFile = $fname;
+ }
+ }
+
+ public function compile($string, $name = null) {
+ $locale = setlocale(LC_NUMERIC, 0);
+ setlocale(LC_NUMERIC, "C");
+
+ $this->parser = $this->makeParser($name);
+ $root = $this->parser->parse($string);
+
+ $this->env = null;
+ $this->scope = null;
+
+ $this->formatter = $this->newFormatter();
+
+ if (!empty($this->registeredVars)) {
+ $this->injectVariables($this->registeredVars);
+ }
+
+ $this->sourceParser = $this->parser; // used for error messages
+ $this->compileBlock($root);
+
+ ob_start();
+ $this->formatter->block($this->scope);
+ $out = ob_get_clean();
+ setlocale(LC_NUMERIC, $locale);
+ return $out;
+ }
+
+ public function compileFile($fname, $outFname = null) {
+ if (!is_readable($fname)) {
+ throw new Exception('load error: failed to find '.$fname);
+ }
+
+ $pi = pathinfo($fname);
+
+ $oldImport = $this->importDir;
+
+ $this->importDir = (array)$this->importDir;
+ $this->importDir[] = $pi['dirname'].'/';
+
+ $this->allParsedFiles = array();
+ $this->addParsedFile($fname);
+
+ $out = $this->compile(file_get_contents($fname), $fname);
+
+ $this->importDir = $oldImport;
+
+ if ($outFname !== null) {
+ return file_put_contents($outFname, $out);
+ }
+
+ return $out;
+ }
+
+ // compile only if changed input has changed or output doesn't exist
+ public function checkedCompile($in, $out) {
+ if (!is_file($out) || filemtime($in) > filemtime($out)) {
+ $this->compileFile($in, $out);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Execute lessphp on a .less file or a lessphp cache structure
+ *
+ * The lessphp cache structure contains information about a specific
+ * less file having been parsed. It can be used as a hint for future
+ * calls to determine whether or not a rebuild is required.
+ *
+ * The cache structure contains two important keys that may be used
+ * externally:
+ *
+ * compiled: The final compiled CSS
+ * updated: The time (in seconds) the CSS was last compiled
+ *
+ * The cache structure is a plain-ol' PHP associative array and can
+ * be serialized and unserialized without a hitch.
+ *
+ * @param mixed $in Input
+ * @param bool $force Force rebuild?
+ * @return array lessphp cache structure
+ */
+ public function cachedCompile($in, $force = false) {
+ // assume no root
+ $root = null;
+
+ if (is_string($in)) {
+ $root = $in;
+ } elseif (is_array($in) and isset($in['root'])) {
+ if ($force or ! isset($in['files'])) {
+ // If we are forcing a recompile or if for some reason the
+ // structure does not contain any file information we should
+ // specify the root to trigger a rebuild.
+ $root = $in['root'];
+ } elseif (isset($in['files']) and is_array($in['files'])) {
+ foreach ($in['files'] as $fname => $ftime ) {
+ if (!file_exists($fname) or filemtime($fname) > $ftime) {
+ // One of the files we knew about previously has changed
+ // so we should look at our incoming root again.
+ $root = $in['root'];
+ break;
+ }
+ }
+ }
+ } else {
+ // TODO: Throw an exception? We got neither a string nor something
+ // that looks like a compatible lessphp cache structure.
+ return null;
+ }
+
+ if ($root !== null) {
+ // If we have a root value which means we should rebuild.
+ $out = array();
+ $out['root'] = $root;
+ $out['compiled'] = $this->compileFile($root);
+ $out['files'] = $this->allParsedFiles();
+ $out['updated'] = time();
+ return $out;
+ } else {
+ // No changes, pass back the structure
+ // we were given initially.
+ return $in;
+ }
+
+ }
+
+ // parse and compile buffer
+ // This is deprecated
+ public function parse($str = null, $initialVariables = null) {
+ if (is_array($str)) {
+ $initialVariables = $str;
+ $str = null;
+ }
+
+ $oldVars = $this->registeredVars;
+ if ($initialVariables !== null) {
+ $this->setVariables($initialVariables);
+ }
+
+ if ($str == null) {
+ if (empty($this->_parseFile)) {
+ throw new exception("nothing to parse");
+ }
+
+ $out = $this->compileFile($this->_parseFile);
+ } else {
+ $out = $this->compile($str);
+ }
+
+ $this->registeredVars = $oldVars;
+ return $out;
+ }
+
+ protected function makeParser($name) {
+ $parser = new lessc_parser($this, $name);
+ $parser->writeComments = $this->preserveComments;
+
+ return $parser;
+ }
+
+ public function setFormatter($name) {
+ $this->formatterName = $name;
+ }
+
+ protected function newFormatter() {
+ $className = "lessc_formatter_lessjs";
+ if (!empty($this->formatterName)) {
+ if (!is_string($this->formatterName))
+ return $this->formatterName;
+ $className = "lessc_formatter_$this->formatterName";
+ }
+
+ return new $className;
+ }
+
+ public function setPreserveComments($preserve) {
+ $this->preserveComments = $preserve;
+ }
+
+ public function registerFunction($name, $func) {
+ $this->libFunctions[$name] = $func;
+ }
+
+ public function unregisterFunction($name) {
+ unset($this->libFunctions[$name]);
+ }
+
+ public function setVariables($variables) {
+ $this->registeredVars = array_merge($this->registeredVars, $variables);
+ }
+
+ public function unsetVariable($name) {
+ unset($this->registeredVars[$name]);
+ }
+
+ public function setImportDir($dirs) {
+ $this->importDir = (array)$dirs;
+ }
+
+ public function addImportDir($dir) {
+ $this->importDir = (array)$this->importDir;
+ $this->importDir[] = $dir;
+ }
+
+ public function allParsedFiles() {
+ return $this->allParsedFiles;
+ }
+
+ protected function addParsedFile($file) {
+ $this->allParsedFiles[realpath($file)] = filemtime($file);
+ }
+
+ /**
+ * Uses the current value of $this->count to show line and line number
+ */
+ protected function throwError($msg = null) {
+ if ($this->sourceLoc >= 0) {
+ $this->sourceParser->throwError($msg, $this->sourceLoc);
+ }
+ throw new exception($msg);
+ }
+
+ // compile file $in to file $out if $in is newer than $out
+ // returns true when it compiles, false otherwise
+ public static function ccompile($in, $out, $less = null) {
+ if ($less === null) {
+ $less = new self;
+ }
+ return $less->checkedCompile($in, $out);
+ }
+
+ public static function cexecute($in, $force = false, $less = null) {
+ if ($less === null) {
+ $less = new self;
+ }
+ return $less->cachedCompile($in, $force);
+ }
+
+ static protected $cssColors = array(
+ 'aliceblue' => '240,248,255',
+ 'antiquewhite' => '250,235,215',
+ 'aqua' => '0,255,255',
+ 'aquamarine' => '127,255,212',
+ 'azure' => '240,255,255',
+ 'beige' => '245,245,220',
+ 'bisque' => '255,228,196',
+ 'black' => '0,0,0',
+ 'blanchedalmond' => '255,235,205',
+ 'blue' => '0,0,255',
+ 'blueviolet' => '138,43,226',
+ 'brown' => '165,42,42',
+ 'burlywood' => '222,184,135',
+ 'cadetblue' => '95,158,160',
+ 'chartreuse' => '127,255,0',
+ 'chocolate' => '210,105,30',
+ 'coral' => '255,127,80',
+ 'cornflowerblue' => '100,149,237',
+ 'cornsilk' => '255,248,220',
+ 'crimson' => '220,20,60',
+ 'cyan' => '0,255,255',
+ 'darkblue' => '0,0,139',
+ 'darkcyan' => '0,139,139',
+ 'darkgoldenrod' => '184,134,11',
+ 'darkgray' => '169,169,169',
+ 'darkgreen' => '0,100,0',
+ 'darkgrey' => '169,169,169',
+ 'darkkhaki' => '189,183,107',
+ 'darkmagenta' => '139,0,139',
+ 'darkolivegreen' => '85,107,47',
+ 'darkorange' => '255,140,0',
+ 'darkorchid' => '153,50,204',
+ 'darkred' => '139,0,0',
+ 'darksalmon' => '233,150,122',
+ 'darkseagreen' => '143,188,143',
+ 'darkslateblue' => '72,61,139',
+ 'darkslategray' => '47,79,79',
+ 'darkslategrey' => '47,79,79',
+ 'darkturquoise' => '0,206,209',
+ 'darkviolet' => '148,0,211',
+ 'deeppink' => '255,20,147',
+ 'deepskyblue' => '0,191,255',
+ 'dimgray' => '105,105,105',
+ 'dimgrey' => '105,105,105',
+ 'dodgerblue' => '30,144,255',
+ 'firebrick' => '178,34,34',
+ 'floralwhite' => '255,250,240',
+ 'forestgreen' => '34,139,34',
+ 'fuchsia' => '255,0,255',
+ 'gainsboro' => '220,220,220',
+ 'ghostwhite' => '248,248,255',
+ 'gold' => '255,215,0',
+ 'goldenrod' => '218,165,32',
+ 'gray' => '128,128,128',
+ 'green' => '0,128,0',
+ 'greenyellow' => '173,255,47',
+ 'grey' => '128,128,128',
+ 'honeydew' => '240,255,240',
+ 'hotpink' => '255,105,180',
+ 'indianred' => '205,92,92',
+ 'indigo' => '75,0,130',
+ 'ivory' => '255,255,240',
+ 'khaki' => '240,230,140',
+ 'lavender' => '230,230,250',
+ 'lavenderblush' => '255,240,245',
+ 'lawngreen' => '124,252,0',
+ 'lemonchiffon' => '255,250,205',
+ 'lightblue' => '173,216,230',
+ 'lightcoral' => '240,128,128',
+ 'lightcyan' => '224,255,255',
+ 'lightgoldenrodyellow' => '250,250,210',
+ 'lightgray' => '211,211,211',
+ 'lightgreen' => '144,238,144',
+ 'lightgrey' => '211,211,211',
+ 'lightpink' => '255,182,193',
+ 'lightsalmon' => '255,160,122',
+ 'lightseagreen' => '32,178,170',
+ 'lightskyblue' => '135,206,250',
+ 'lightslategray' => '119,136,153',
+ 'lightslategrey' => '119,136,153',
+ 'lightsteelblue' => '176,196,222',
+ 'lightyellow' => '255,255,224',
+ 'lime' => '0,255,0',
+ 'limegreen' => '50,205,50',
+ 'linen' => '250,240,230',
+ 'magenta' => '255,0,255',
+ 'maroon' => '128,0,0',
+ 'mediumaquamarine' => '102,205,170',
+ 'mediumblue' => '0,0,205',
+ 'mediumorchid' => '186,85,211',
+ 'mediumpurple' => '147,112,219',
+ 'mediumseagreen' => '60,179,113',
+ 'mediumslateblue' => '123,104,238',
+ 'mediumspringgreen' => '0,250,154',
+ 'mediumturquoise' => '72,209,204',
+ 'mediumvioletred' => '199,21,133',
+ 'midnightblue' => '25,25,112',
+ 'mintcream' => '245,255,250',
+ 'mistyrose' => '255,228,225',
+ 'moccasin' => '255,228,181',
+ 'navajowhite' => '255,222,173',
+ 'navy' => '0,0,128',
+ 'oldlace' => '253,245,230',
+ 'olive' => '128,128,0',
+ 'olivedrab' => '107,142,35',
+ 'orange' => '255,165,0',
+ 'orangered' => '255,69,0',
+ 'orchid' => '218,112,214',
+ 'palegoldenrod' => '238,232,170',
+ 'palegreen' => '152,251,152',
+ 'paleturquoise' => '175,238,238',
+ 'palevioletred' => '219,112,147',
+ 'papayawhip' => '255,239,213',
+ 'peachpuff' => '255,218,185',
+ 'peru' => '205,133,63',
+ 'pink' => '255,192,203',
+ 'plum' => '221,160,221',
+ 'powderblue' => '176,224,230',
+ 'purple' => '128,0,128',
+ 'red' => '255,0,0',
+ 'rosybrown' => '188,143,143',
+ 'royalblue' => '65,105,225',
+ 'saddlebrown' => '139,69,19',
+ 'salmon' => '250,128,114',
+ 'sandybrown' => '244,164,96',
+ 'seagreen' => '46,139,87',
+ 'seashell' => '255,245,238',
+ 'sienna' => '160,82,45',
+ 'silver' => '192,192,192',
+ 'skyblue' => '135,206,235',
+ 'slateblue' => '106,90,205',
+ 'slategray' => '112,128,144',
+ 'slategrey' => '112,128,144',
+ 'snow' => '255,250,250',
+ 'springgreen' => '0,255,127',
+ 'steelblue' => '70,130,180',
+ 'tan' => '210,180,140',
+ 'teal' => '0,128,128',
+ 'thistle' => '216,191,216',
+ 'tomato' => '255,99,71',
+ 'transparent' => '0,0,0,0',
+ 'turquoise' => '64,224,208',
+ 'violet' => '238,130,238',
+ 'wheat' => '245,222,179',
+ 'white' => '255,255,255',
+ 'whitesmoke' => '245,245,245',
+ 'yellow' => '255,255,0',
+ 'yellowgreen' => '154,205,50'
+ );
+}
+
+// responsible for taking a string of LESS code and converting it into a
+// syntax tree
+class lessc_parser {
+ static protected $nextBlockId = 0; // used to uniquely identify blocks
+
+ static protected $precedence = array(
+ '=<' => 0,
+ '>=' => 0,
+ '=' => 0,
+ '<' => 0,
+ '>' => 0,
+
+ '+' => 1,
+ '-' => 1,
+ '*' => 2,
+ '/' => 2,
+ '%' => 2,
+ );
+
+ static protected $whitePattern;
+ static protected $commentMulti;
+
+ static protected $commentSingle = "//";
+ static protected $commentMultiLeft = "/*";
+ static protected $commentMultiRight = "*/";
+
+ // regex string to match any of the operators
+ static protected $operatorString;
+
+ // these properties will supress division unless it's inside parenthases
+ static protected $supressDivisionProps =
+ array('/border-radius$/i', '/^font$/i');
+
+ protected $blockDirectives = array("font-face", "keyframes", "page", "-moz-document", "viewport", "-moz-viewport", "-o-viewport", "-ms-viewport");
+ protected $lineDirectives = array("charset");
+
+ /**
+ * if we are in parens we can be more liberal with whitespace around
+ * operators because it must evaluate to a single value and thus is less
+ * ambiguous.
+ *
+ * Consider:
+ * property1: 10 -5; // is two numbers, 10 and -5
+ * property2: (10 -5); // should evaluate to 5
+ */
+ protected $inParens = false;
+
+ // caches preg escaped literals
+ static protected $literalCache = array();
+
+ public function __construct($lessc, $sourceName = null) {
+ $this->eatWhiteDefault = true;
+ // reference to less needed for vPrefix, mPrefix, and parentSelector
+ $this->lessc = $lessc;
+
+ $this->sourceName = $sourceName; // name used for error messages
+
+ $this->writeComments = false;
+
+ if (!self::$operatorString) {
+ self::$operatorString =
+ '('.implode('|', array_map(array('lessc', 'preg_quote'),
+ array_keys(self::$precedence))).')';
+
+ $commentSingle = lessc::preg_quote(self::$commentSingle);
+ $commentMultiLeft = lessc::preg_quote(self::$commentMultiLeft);
+ $commentMultiRight = lessc::preg_quote(self::$commentMultiRight);
+
+ self::$commentMulti = $commentMultiLeft.'.*?'.$commentMultiRight;
+ self::$whitePattern = '/'.$commentSingle.'[^\n]*\s*|('.self::$commentMulti.')\s*|\s+/Ais';
+ }
+ }
+
+ public function parse($buffer) {
+ $this->count = 0;
+ $this->line = 1;
+
+ $this->env = null; // block stack
+ $this->buffer = $this->writeComments ? $buffer : $this->removeComments($buffer);
+ $this->pushSpecialBlock("root");
+ $this->eatWhiteDefault = true;
+ $this->seenComments = array();
+
+ // trim whitespace on head
+ // if (preg_match('/^\s+/', $this->buffer, $m)) {
+ // $this->line += substr_count($m[0], "\n");
+ // $this->buffer = ltrim($this->buffer);
+ // }
+ $this->whitespace();
+
+ // parse the entire file
+ $lastCount = $this->count;
+ while (false !== $this->parseChunk());
+
+ if ($this->count != strlen($this->buffer))
+ $this->throwError();
+
+ // TODO report where the block was opened
+ if (!is_null($this->env->parent))
+ throw new exception('parse error: unclosed block');
+
+ return $this->env;
+ }
+
+ /**
+ * Parse a single chunk off the head of the buffer and append it to the
+ * current parse environment.
+ * Returns false when the buffer is empty, or when there is an error.
+ *
+ * This function is called repeatedly until the entire document is
+ * parsed.
+ *
+ * This parser is most similar to a recursive descent parser. Single
+ * functions represent discrete grammatical rules for the language, and
+ * they are able to capture the text that represents those rules.
+ *
+ * Consider the function lessc::keyword(). (all parse functions are
+ * structured the same)
+ *
+ * The function takes a single reference argument. When calling the
+ * function it will attempt to match a keyword on the head of the buffer.
+ * If it is successful, it will place the keyword in the referenced
+ * argument, advance the position in the buffer, and return true. If it
+ * fails then it won't advance the buffer and it will return false.
+ *
+ * All of these parse functions are powered by lessc::match(), which behaves
+ * the same way, but takes a literal regular expression. Sometimes it is
+ * more convenient to use match instead of creating a new function.
+ *
+ * Because of the format of the functions, to parse an entire string of
+ * grammatical rules, you can chain them together using &&.
+ *
+ * But, if some of the rules in the chain succeed before one fails, then
+ * the buffer position will be left at an invalid state. In order to
+ * avoid this, lessc::seek() is used to remember and set buffer positions.
+ *
+ * Before parsing a chain, use $s = $this->seek() to remember the current
+ * position into $s. Then if a chain fails, use $this->seek($s) to
+ * go back where we started.
+ */
+ protected function parseChunk() {
+ if (empty($this->buffer)) return false;
+ $s = $this->seek();
+
+ // setting a property
+ if ($this->keyword($key) && $this->assign() &&
+ $this->propertyValue($value, $key) && $this->end())
+ {
+ $this->append(array('assign', $key, $value), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+
+ // look for special css blocks
+ if ($this->literal('@', false)) {
+ $this->count--;
+
+ // media
+ if ($this->literal('@media')) {
+ if (($this->mediaQueryList($mediaQueries) || true)
+ && $this->literal('{'))
+ {
+ $media = $this->pushSpecialBlock("media");
+ $media->queries = is_null($mediaQueries) ? array() : $mediaQueries;
+ return true;
+ } else {
+ $this->seek($s);
+ return false;
+ }
+ }
+
+ if ($this->literal("@", false) && $this->keyword($dirName)) {
+ if ($this->isDirective($dirName, $this->blockDirectives)) {
+ if (($this->openString("{", $dirValue, null, array(";")) || true) &&
+ $this->literal("{"))
+ {
+ $dir = $this->pushSpecialBlock("directive");
+ $dir->name = $dirName;
+ if (isset($dirValue)) $dir->value = $dirValue;
+ return true;
+ }
+ } elseif ($this->isDirective($dirName, $this->lineDirectives)) {
+ if ($this->propertyValue($dirValue) && $this->end()) {
+ $this->append(array("directive", $dirName, $dirValue));
+ return true;
+ }
+ }
+ }
+
+ $this->seek($s);
+ }
+
+ // setting a variable
+ if ($this->variable($var) && $this->assign() &&
+ $this->propertyValue($value) && $this->end())
+ {
+ $this->append(array('assign', $var, $value), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->import($importValue)) {
+ $this->append($importValue, $s);
+ return true;
+ }
+
+ // opening parametric mixin
+ if ($this->tag($tag, true) && $this->argumentDef($args, $isVararg) &&
+ ($this->guards($guards) || true) &&
+ $this->literal('{'))
+ {
+ $block = $this->pushBlock($this->fixTags(array($tag)));
+ $block->args = $args;
+ $block->isVararg = $isVararg;
+ if (!empty($guards)) $block->guards = $guards;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // opening a simple block
+ if ($this->tags($tags) && $this->literal('{')) {
+ $tags = $this->fixTags($tags);
+ $this->pushBlock($tags);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // closing a block
+ if ($this->literal('}', false)) {
+ try {
+ $block = $this->pop();
+ } catch (exception $e) {
+ $this->seek($s);
+ $this->throwError($e->getMessage());
+ }
+
+ $hidden = false;
+ if (is_null($block->type)) {
+ $hidden = true;
+ if (!isset($block->args)) {
+ foreach ($block->tags as $tag) {
+ if (!is_string($tag) || $tag{0} != $this->lessc->mPrefix) {
+ $hidden = false;
+ break;
+ }
+ }
+ }
+
+ foreach ($block->tags as $tag) {
+ if (is_string($tag)) {
+ $this->env->children[$tag][] = $block;
+ }
+ }
+ }
+
+ if (!$hidden) {
+ $this->append(array('block', $block), $s);
+ }
+
+ // this is done here so comments aren't bundled into he block that
+ // was just closed
+ $this->whitespace();
+ return true;
+ }
+
+ // mixin
+ if ($this->mixinTags($tags) &&
+ ($this->argumentValues($argv) || true) &&
+ ($this->keyword($suffix) || true) && $this->end())
+ {
+ $tags = $this->fixTags($tags);
+ $this->append(array('mixin', $tags, $argv, $suffix), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // spare ;
+ if ($this->literal(';')) return true;
+
+ return false; // got nothing, throw error
+ }
+
+ protected function isDirective($dirname, $directives) {
+ // TODO: cache pattern in parser
+ $pattern = implode("|",
+ array_map(array("lessc", "preg_quote"), $directives));
+ $pattern = '/^(-[a-z-]+-)?(' . $pattern . ')$/i';
+
+ return preg_match($pattern, $dirname);
+ }
+
+ protected function fixTags($tags) {
+ // move @ tags out of variable namespace
+ foreach ($tags as &$tag) {
+ if ($tag{0} == $this->lessc->vPrefix)
+ $tag[0] = $this->lessc->mPrefix;
+ }
+ return $tags;
+ }
+
+ // a list of expressions
+ protected function expressionList(&$exps) {
+ $values = array();
+
+ while ($this->expression($exp)) {
+ $values[] = $exp;
+ }
+
+ if (count($values) == 0) return false;
+
+ $exps = lessc::compressList($values, ' ');
+ return true;
+ }
+
+ /**
+ * Attempt to consume an expression.
+ * @link http://en.wikipedia.org/wiki/Operator-precedence_parser#Pseudo-code
+ */
+ protected function expression(&$out) {
+ if ($this->value($lhs)) {
+ $out = $this->expHelper($lhs, 0);
+
+ // look for / shorthand
+ if (!empty($this->env->supressedDivision)) {
+ unset($this->env->supressedDivision);
+ $s = $this->seek();
+ if ($this->literal("/") && $this->value($rhs)) {
+ $out = array("list", "",
+ array($out, array("keyword", "/"), $rhs));
+ } else {
+ $this->seek($s);
+ }
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * recursively parse infix equation with $lhs at precedence $minP
+ */
+ protected function expHelper($lhs, $minP) {
+ $this->inExp = true;
+ $ss = $this->seek();
+
+ while (true) {
+ $whiteBefore = isset($this->buffer[$this->count - 1]) &&
+ ctype_space($this->buffer[$this->count - 1]);
+
+ // If there is whitespace before the operator, then we require
+ // whitespace after the operator for it to be an expression
+ $needWhite = $whiteBefore && !$this->inParens;
+
+ if ($this->match(self::$operatorString.($needWhite ? '\s' : ''), $m) && self::$precedence[$m[1]] >= $minP) {
+ if (!$this->inParens && isset($this->env->currentProperty) && $m[1] == "/" && empty($this->env->supressedDivision)) {
+ foreach (self::$supressDivisionProps as $pattern) {
+ if (preg_match($pattern, $this->env->currentProperty)) {
+ $this->env->supressedDivision = true;
+ break 2;
+ }
+ }
+ }
+
+
+ $whiteAfter = isset($this->buffer[$this->count - 1]) &&
+ ctype_space($this->buffer[$this->count - 1]);
+
+ if (!$this->value($rhs)) break;
+
+ // peek for next operator to see what to do with rhs
+ if ($this->peek(self::$operatorString, $next) && self::$precedence[$next[1]] > self::$precedence[$m[1]]) {
+ $rhs = $this->expHelper($rhs, self::$precedence[$next[1]]);
+ }
+
+ $lhs = array('expression', $m[1], $lhs, $rhs, $whiteBefore, $whiteAfter);
+ $ss = $this->seek();
+
+ continue;
+ }
+
+ break;
+ }
+
+ $this->seek($ss);
+
+ return $lhs;
+ }
+
+ // consume a list of values for a property
+ public function propertyValue(&$value, $keyName = null) {
+ $values = array();
+
+ if ($keyName !== null) $this->env->currentProperty = $keyName;
+
+ $s = null;
+ while ($this->expressionList($v)) {
+ $values[] = $v;
+ $s = $this->seek();
+ if (!$this->literal(',')) break;
+ }
+
+ if ($s) $this->seek($s);
+
+ if ($keyName !== null) unset($this->env->currentProperty);
+
+ if (count($values) == 0) return false;
+
+ $value = lessc::compressList($values, ', ');
+ return true;
+ }
+
+ protected function parenValue(&$out) {
+ $s = $this->seek();
+
+ // speed shortcut
+ if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "(") {
+ return false;
+ }
+
+ $inParens = $this->inParens;
+ if ($this->literal("(") &&
+ ($this->inParens = true) && $this->expression($exp) &&
+ $this->literal(")"))
+ {
+ $out = $exp;
+ $this->inParens = $inParens;
+ return true;
+ } else {
+ $this->inParens = $inParens;
+ $this->seek($s);
+ }
+
+ return false;
+ }
+
+ // a single value
+ protected function value(&$value) {
+ $s = $this->seek();
+
+ // speed shortcut
+ if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "-") {
+ // negation
+ if ($this->literal("-", false) &&
+ (($this->variable($inner) && $inner = array("variable", $inner)) ||
+ $this->unit($inner) ||
+ $this->parenValue($inner)))
+ {
+ $value = array("unary", "-", $inner);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+ }
+
+ if ($this->parenValue($value)) return true;
+ if ($this->unit($value)) return true;
+ if ($this->color($value)) return true;
+ if ($this->func($value)) return true;
+ if ($this->string($value)) return true;
+
+ if ($this->keyword($word)) {
+ $value = array('keyword', $word);
+ return true;
+ }
+
+ // try a variable
+ if ($this->variable($var)) {
+ $value = array('variable', $var);
+ return true;
+ }
+
+ // unquote string (should this work on any type?
+ if ($this->literal("~") && $this->string($str)) {
+ $value = array("escape", $str);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // css hack: \0
+ if ($this->literal('\\') && $this->match('([0-9]+)', $m)) {
+ $value = array('keyword', '\\'.$m[1]);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ return false;
+ }
+
+ // an import statement
+ protected function import(&$out) {
+ $s = $this->seek();
+ if (!$this->literal('@import')) return false;
+
+ // @import "something.css" media;
+ // @import url("something.css") media;
+ // @import url(something.css) media;
+
+ if ($this->propertyValue($value)) {
+ $out = array("import", $value);
+ return true;
+ }
+ }
+
+ protected function mediaQueryList(&$out) {
+ if ($this->genericList($list, "mediaQuery", ",", false)) {
+ $out = $list[2];
+ return true;
+ }
+ return false;
+ }
+
+ protected function mediaQuery(&$out) {
+ $s = $this->seek();
+
+ $expressions = null;
+ $parts = array();
+
+ if (($this->literal("only") && ($only = true) || $this->literal("not") && ($not = true) || true) && $this->keyword($mediaType)) {
+ $prop = array("mediaType");
+ if (isset($only)) $prop[] = "only";
+ if (isset($not)) $prop[] = "not";
+ $prop[] = $mediaType;
+ $parts[] = $prop;
+ } else {
+ $this->seek($s);
+ }
+
+
+ if (!empty($mediaType) && !$this->literal("and")) {
+ // ~
+ } else {
+ $this->genericList($expressions, "mediaExpression", "and", false);
+ if (is_array($expressions)) $parts = array_merge($parts, $expressions[2]);
+ }
+
+ if (count($parts) == 0) {
+ $this->seek($s);
+ return false;
+ }
+
+ $out = $parts;
+ return true;
+ }
+
+ protected function mediaExpression(&$out) {
+ $s = $this->seek();
+ $value = null;
+ if ($this->literal("(") &&
+ $this->keyword($feature) &&
+ ($this->literal(":") && $this->expression($value) || true) &&
+ $this->literal(")"))
+ {
+ $out = array("mediaExp", $feature);
+ if ($value) $out[] = $value;
+ return true;
+ } elseif ($this->variable($variable)) {
+ $out = array('variable', $variable);
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ // an unbounded string stopped by $end
+ protected function openString($end, &$out, $nestingOpen=null, $rejectStrs = null) {
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ $stop = array("'", '"', "@{", $end);
+ $stop = array_map(array("lessc", "preg_quote"), $stop);
+ // $stop[] = self::$commentMulti;
+
+ if (!is_null($rejectStrs)) {
+ $stop = array_merge($stop, $rejectStrs);
+ }
+
+ $patt = '(.*?)('.implode("|", $stop).')';
+
+ $nestingLevel = 0;
+
+ $content = array();
+ while ($this->match($patt, $m, false)) {
+ if (!empty($m[1])) {
+ $content[] = $m[1];
+ if ($nestingOpen) {
+ $nestingLevel += substr_count($m[1], $nestingOpen);
+ }
+ }
+
+ $tok = $m[2];
+
+ $this->count-= strlen($tok);
+ if ($tok == $end) {
+ if ($nestingLevel == 0) {
+ break;
+ } else {
+ $nestingLevel--;
+ }
+ }
+
+ if (($tok == "'" || $tok == '"') && $this->string($str)) {
+ $content[] = $str;
+ continue;
+ }
+
+ if ($tok == "@{" && $this->interpolation($inter)) {
+ $content[] = $inter;
+ continue;
+ }
+
+ if (!empty($rejectStrs) && in_array($tok, $rejectStrs)) {
+ break;
+ }
+
+ $content[] = $tok;
+ $this->count+= strlen($tok);
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if (count($content) == 0) return false;
+
+ // trim the end
+ if (is_string(end($content))) {
+ $content[count($content) - 1] = rtrim(end($content));
+ }
+
+ $out = array("string", "", $content);
+ return true;
+ }
+
+ protected function string(&$out) {
+ $s = $this->seek();
+ if ($this->literal('"', false)) {
+ $delim = '"';
+ } elseif ($this->literal("'", false)) {
+ $delim = "'";
+ } else {
+ return false;
+ }
+
+ $content = array();
+
+ // look for either ending delim , escape, or string interpolation
+ $patt = '([^\n]*?)(@\{|\\\\|' .
+ lessc::preg_quote($delim).')';
+
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ while ($this->match($patt, $m, false)) {
+ $content[] = $m[1];
+ if ($m[2] == "@{") {
+ $this->count -= strlen($m[2]);
+ if ($this->interpolation($inter, false)) {
+ $content[] = $inter;
+ } else {
+ $this->count += strlen($m[2]);
+ $content[] = "@{"; // ignore it
+ }
+ } elseif ($m[2] == '\\') {
+ $content[] = $m[2];
+ if ($this->literal($delim, false)) {
+ $content[] = $delim;
+ }
+ } else {
+ $this->count -= strlen($delim);
+ break; // delim
+ }
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if ($this->literal($delim)) {
+ $out = array("string", $delim, $content);
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function interpolation(&$out) {
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = true;
+
+ $s = $this->seek();
+ if ($this->literal("@{") &&
+ $this->openString("}", $interp, null, array("'", '"', ";")) &&
+ $this->literal("}", false))
+ {
+ $out = array("interpolate", $interp);
+ $this->eatWhiteDefault = $oldWhite;
+ if ($this->eatWhiteDefault) $this->whitespace();
+ return true;
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+ $this->seek($s);
+ return false;
+ }
+
+ protected function unit(&$unit) {
+ // speed shortcut
+ if (isset($this->buffer[$this->count])) {
+ $char = $this->buffer[$this->count];
+ if (!ctype_digit($char) && $char != ".") return false;
+ }
+
+ if ($this->match('([0-9]+(?:\.[0-9]*)?|\.[0-9]+)([%a-zA-Z]+)?', $m)) {
+ $unit = array("number", $m[1], empty($m[2]) ? "" : $m[2]);
+ return true;
+ }
+ return false;
+ }
+
+ // a # color
+ protected function color(&$out) {
+ if ($this->match('(#(?:[0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{3}))', $m)) {
+ if (strlen($m[1]) > 7) {
+ $out = array("string", "", array($m[1]));
+ } else {
+ $out = array("raw_color", $m[1]);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ // consume a list of property values delimited by ; and wrapped in ()
+ protected function argumentValues(&$args, $delim = ',') {
+ $s = $this->seek();
+ if (!$this->literal('(')) return false;
+
+ $values = array();
+ while (true) {
+ if ($this->expressionList($value)) $values[] = $value;
+ if (!$this->literal($delim)) break;
+ else {
+ if ($value == null) $values[] = null;
+ $value = null;
+ }
+ }
+
+ if (!$this->literal(')')) {
+ $this->seek($s);
+ return false;
+ }
+
+ $args = $values;
+ return true;
+ }
+
+ // consume an argument definition list surrounded by ()
+ // each argument is a variable name with optional value
+ // or at the end a ... or a variable named followed by ...
+ protected function argumentDef(&$args, &$isVararg, $delim = ',') {
+ $s = $this->seek();
+ if (!$this->literal('(')) return false;
+
+ $values = array();
+
+ $isVararg = false;
+ while (true) {
+ if ($this->literal("...")) {
+ $isVararg = true;
+ break;
+ }
+
+ if ($this->variable($vname)) {
+ $arg = array("arg", $vname);
+ $ss = $this->seek();
+ if ($this->assign() && $this->expressionList($value)) {
+ $arg[] = $value;
+ } else {
+ $this->seek($ss);
+ if ($this->literal("...")) {
+ $arg[0] = "rest";
+ $isVararg = true;
+ }
+ }
+ $values[] = $arg;
+ if ($isVararg) break;
+ continue;
+ }
+
+ if ($this->value($literal)) {
+ $values[] = array("lit", $literal);
+ }
+
+ if (!$this->literal($delim)) break;
+ }
+
+ if (!$this->literal(')')) {
+ $this->seek($s);
+ return false;
+ }
+
+ $args = $values;
+
+ return true;
+ }
+
+ // consume a list of tags
+ // this accepts a hanging delimiter
+ protected function tags(&$tags, $simple = false, $delim = ',') {
+ $tags = array();
+ while ($this->tag($tt, $simple)) {
+ $tags[] = $tt;
+ if (!$this->literal($delim)) break;
+ }
+ if (count($tags) == 0) return false;
+
+ return true;
+ }
+
+ // list of tags of specifying mixin path
+ // optionally separated by > (lazy, accepts extra >)
+ protected function mixinTags(&$tags) {
+ $s = $this->seek();
+ $tags = array();
+ while ($this->tag($tt, true)) {
+ $tags[] = $tt;
+ $this->literal(">");
+ }
+
+ if (count($tags) == 0) return false;
+
+ return true;
+ }
+
+ // a bracketed value (contained within in a tag definition)
+ protected function tagBracket(&$value) {
+ // speed shortcut
+ if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "[") {
+ return false;
+ }
+
+ $s = $this->seek();
+ if ($this->literal('[') && $this->to(']', $c, true) && $this->literal(']', false)) {
+ $value = '['.$c.']';
+ // whitespace?
+ if ($this->whitespace()) $value .= " ";
+
+ // escape parent selector, (yuck)
+ $value = str_replace($this->lessc->parentSelector, "$&$", $value);
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function tagExpression(&$value) {
+ $s = $this->seek();
+ if ($this->literal("(") && $this->expression($exp) && $this->literal(")")) {
+ $value = array('exp', $exp);
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ // a space separated list of selectors
+ protected function tag(&$tag, $simple = false) {
+ if ($simple)
+ $chars = '^@,:;{}\][>\(\) "\'';
+ else
+ $chars = '^@,;{}["\'';
+
+ $s = $this->seek();
+
+ if (!$simple && $this->tagExpression($tag)) {
+ return true;
+ }
+
+ $hasExpression = false;
+ $parts = array();
+ while ($this->tagBracket($first)) $parts[] = $first;
+
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ while (true) {
+ if ($this->match('(['.$chars.'0-9]['.$chars.']*)', $m)) {
+ $parts[] = $m[1];
+ if ($simple) break;
+
+ while ($this->tagBracket($brack)) {
+ $parts[] = $brack;
+ }
+ continue;
+ }
+
+ if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "@") {
+ if ($this->interpolation($interp)) {
+ $hasExpression = true;
+ $interp[2] = true; // don't unescape
+ $parts[] = $interp;
+ continue;
+ }
+
+ if ($this->literal("@")) {
+ $parts[] = "@";
+ continue;
+ }
+ }
+
+ if ($this->unit($unit)) { // for keyframes
+ $parts[] = $unit[1];
+ $parts[] = $unit[2];
+ continue;
+ }
+
+ break;
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+ if (!$parts) {
+ $this->seek($s);
+ return false;
+ }
+
+ if ($hasExpression) {
+ $tag = array("exp", array("string", "", $parts));
+ } else {
+ $tag = trim(implode($parts));
+ }
+
+ $this->whitespace();
+ return true;
+ }
+
+ // a css function
+ protected function func(&$func) {
+ $s = $this->seek();
+
+ if ($this->match('(%|[\w\-_][\w\-_:\.]+|[\w_])', $m) && $this->literal('(')) {
+ $fname = $m[1];
+
+ $sPreArgs = $this->seek();
+
+ $args = array();
+ while (true) {
+ $ss = $this->seek();
+ // this ugly nonsense is for ie filter properties
+ if ($this->keyword($name) && $this->literal('=') && $this->expressionList($value)) {
+ $args[] = array("string", "", array($name, "=", $value));
+ } else {
+ $this->seek($ss);
+ if ($this->expressionList($value)) {
+ $args[] = $value;
+ }
+ }
+
+ if (!$this->literal(',')) break;
+ }
+ $args = array('list', ',', $args);
+
+ if ($this->literal(')')) {
+ $func = array('function', $fname, $args);
+ return true;
+ } elseif ($fname == 'url') {
+ // couldn't parse and in url? treat as string
+ $this->seek($sPreArgs);
+ if ($this->openString(")", $string) && $this->literal(")")) {
+ $func = array('function', $fname, $string);
+ return true;
+ }
+ }
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ // consume a less variable
+ protected function variable(&$name) {
+ $s = $this->seek();
+ if ($this->literal($this->lessc->vPrefix, false) &&
+ ($this->variable($sub) || $this->keyword($name)))
+ {
+ if (!empty($sub)) {
+ $name = array('variable', $sub);
+ } else {
+ $name = $this->lessc->vPrefix.$name;
+ }
+ return true;
+ }
+
+ $name = null;
+ $this->seek($s);
+ return false;
+ }
+
+ /**
+ * Consume an assignment operator
+ * Can optionally take a name that will be set to the current property name
+ */
+ protected function assign($name = null) {
+ if ($name) $this->currentProperty = $name;
+ return $this->literal(':') || $this->literal('=');
+ }
+
+ // consume a keyword
+ protected function keyword(&$word) {
+ if ($this->match('([\w_\-\*!"][\w\-_"]*)', $m)) {
+ $word = $m[1];
+ return true;
+ }
+ return false;
+ }
+
+ // consume an end of statement delimiter
+ protected function end() {
+ if ($this->literal(';')) {
+ return true;
+ } elseif ($this->count == strlen($this->buffer) || $this->buffer[$this->count] == '}') {
+ // if there is end of file or a closing block next then we don't need a ;
+ return true;
+ }
+ return false;
+ }
+
+ protected function guards(&$guards) {
+ $s = $this->seek();
+
+ if (!$this->literal("when")) {
+ $this->seek($s);
+ return false;
+ }
+
+ $guards = array();
+
+ while ($this->guardGroup($g)) {
+ $guards[] = $g;
+ if (!$this->literal(",")) break;
+ }
+
+ if (count($guards) == 0) {
+ $guards = null;
+ $this->seek($s);
+ return false;
+ }
+
+ return true;
+ }
+
+ // a bunch of guards that are and'd together
+ // TODO rename to guardGroup
+ protected function guardGroup(&$guardGroup) {
+ $s = $this->seek();
+ $guardGroup = array();
+ while ($this->guard($guard)) {
+ $guardGroup[] = $guard;
+ if (!$this->literal("and")) break;
+ }
+
+ if (count($guardGroup) == 0) {
+ $guardGroup = null;
+ $this->seek($s);
+ return false;
+ }
+
+ return true;
+ }
+
+ protected function guard(&$guard) {
+ $s = $this->seek();
+ $negate = $this->literal("not");
+
+ if ($this->literal("(") && $this->expression($exp) && $this->literal(")")) {
+ $guard = $exp;
+ if ($negate) $guard = array("negate", $guard);
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ /* raw parsing functions */
+
+ protected function literal($what, $eatWhitespace = null) {
+ if ($eatWhitespace === null) $eatWhitespace = $this->eatWhiteDefault;
+
+ // shortcut on single letter
+ if (!isset($what[1]) && isset($this->buffer[$this->count])) {
+ if ($this->buffer[$this->count] == $what) {
+ if (!$eatWhitespace) {
+ $this->count++;
+ return true;
+ }
+ // goes below...
+ } else {
+ return false;
+ }
+ }
+
+ if (!isset(self::$literalCache[$what])) {
+ self::$literalCache[$what] = lessc::preg_quote($what);
+ }
+
+ return $this->match(self::$literalCache[$what], $m, $eatWhitespace);
+ }
+
+ protected function genericList(&$out, $parseItem, $delim="", $flatten=true) {
+ $s = $this->seek();
+ $items = array();
+ while ($this->$parseItem($value)) {
+ $items[] = $value;
+ if ($delim) {
+ if (!$this->literal($delim)) break;
+ }
+ }
+
+ if (count($items) == 0) {
+ $this->seek($s);
+ return false;
+ }
+
+ if ($flatten && count($items) == 1) {
+ $out = $items[0];
+ } else {
+ $out = array("list", $delim, $items);
+ }
+
+ return true;
+ }
+
+
+ // advance counter to next occurrence of $what
+ // $until - don't include $what in advance
+ // $allowNewline, if string, will be used as valid char set
+ protected function to($what, &$out, $until = false, $allowNewline = false) {
+ if (is_string($allowNewline)) {
+ $validChars = $allowNewline;
+ } else {
+ $validChars = $allowNewline ? "." : "[^\n]";
+ }
+ if (!$this->match('('.$validChars.'*?)'.lessc::preg_quote($what), $m, !$until)) return false;
+ if ($until) $this->count -= strlen($what); // give back $what
+ $out = $m[1];
+ return true;
+ }
+
+ // try to match something on head of buffer
+ protected function match($regex, &$out, $eatWhitespace = null) {
+ if ($eatWhitespace === null) $eatWhitespace = $this->eatWhiteDefault;
+
+ $r = '/'.$regex.($eatWhitespace && !$this->writeComments ? '\s*' : '').'/Ais';
+ if (preg_match($r, $this->buffer, $out, null, $this->count)) {
+ $this->count += strlen($out[0]);
+ if ($eatWhitespace && $this->writeComments) $this->whitespace();
+ return true;
+ }
+ return false;
+ }
+
+ // match some whitespace
+ protected function whitespace() {
+ if ($this->writeComments) {
+ $gotWhite = false;
+ while (preg_match(self::$whitePattern, $this->buffer, $m, null, $this->count)) {
+ if (isset($m[1]) && empty($this->commentsSeen[$this->count])) {
+ $this->append(array("comment", $m[1]));
+ $this->commentsSeen[$this->count] = true;
+ }
+ $this->count += strlen($m[0]);
+ $gotWhite = true;
+ }
+ return $gotWhite;
+ } else {
+ $this->match("", $m);
+ return strlen($m[0]) > 0;
+ }
+ }
+
+ // match something without consuming it
+ protected function peek($regex, &$out = null, $from=null) {
+ if (is_null($from)) $from = $this->count;
+ $r = '/'.$regex.'/Ais';
+ $result = preg_match($r, $this->buffer, $out, null, $from);
+
+ return $result;
+ }
+
+ // seek to a spot in the buffer or return where we are on no argument
+ protected function seek($where = null) {
+ if ($where === null) return $this->count;
+ else $this->count = $where;
+ return true;
+ }
+
+ /* misc functions */
+
+ public function throwError($msg = "parse error", $count = null) {
+ $count = is_null($count) ? $this->count : $count;
+
+ $line = $this->line +
+ substr_count(substr($this->buffer, 0, $count), "\n");
+
+ if (!empty($this->sourceName)) {
+ $loc = "$this->sourceName on line $line";
+ } else {
+ $loc = "line: $line";
+ }
+
+ // TODO this depends on $this->count
+ if ($this->peek("(.*?)(\n|$)", $m, $count)) {
+ throw new exception("$msg: failed at `$m[1]` $loc");
+ } else {
+ throw new exception("$msg: $loc");
+ }
+ }
+
+ protected function pushBlock($selectors=null, $type=null) {
+ $b = new stdclass;
+ $b->parent = $this->env;
+
+ $b->type = $type;
+ $b->id = self::$nextBlockId++;
+
+ $b->isVararg = false; // TODO: kill me from here
+ $b->tags = $selectors;
+
+ $b->props = array();
+ $b->children = array();
+
+ $this->env = $b;
+ return $b;
+ }
+
+ // push a block that doesn't multiply tags
+ protected function pushSpecialBlock($type) {
+ return $this->pushBlock(null, $type);
+ }
+
+ // append a property to the current block
+ protected function append($prop, $pos = null) {
+ if ($pos !== null) $prop[-1] = $pos;
+ $this->env->props[] = $prop;
+ }
+
+ // pop something off the stack
+ protected function pop() {
+ $old = $this->env;
+ $this->env = $this->env->parent;
+ return $old;
+ }
+
+ // remove comments from $text
+ // todo: make it work for all functions, not just url
+ protected function removeComments($text) {
+ $look = array(
+ 'url(', '//', '/*', '"', "'"
+ );
+
+ $out = '';
+ $min = null;
+ while (true) {
+ // find the next item
+ foreach ($look as $token) {
+ $pos = strpos($text, $token);
+ if ($pos !== false) {
+ if (!isset($min) || $pos < $min[1]) $min = array($token, $pos);
+ }
+ }
+
+ if (is_null($min)) break;
+
+ $count = $min[1];
+ $skip = 0;
+ $newlines = 0;
+ switch ($min[0]) {
+ case 'url(':
+ if (preg_match('/url\(.*?\)/', $text, $m, 0, $count))
+ $count += strlen($m[0]) - strlen($min[0]);
+ break;
+ case '"':
+ case "'":
+ if (preg_match('/'.$min[0].'.*?'.$min[0].'/', $text, $m, 0, $count))
+ $count += strlen($m[0]) - 1;
+ break;
+ case '//':
+ $skip = strpos($text, "\n", $count);
+ if ($skip === false) $skip = strlen($text) - $count;
+ else $skip -= $count;
+ break;
+ case '/*':
+ if (preg_match('/\/\*.*?\*\//s', $text, $m, 0, $count)) {
+ $skip = strlen($m[0]);
+ $newlines = substr_count($m[0], "\n");
+ }
+ break;
+ }
+
+ if ($skip == 0) $count += strlen($min[0]);
+
+ $out .= substr($text, 0, $count).str_repeat("\n", $newlines);
+ $text = substr($text, $count + $skip);
+
+ $min = null;
+ }
+
+ return $out.$text;
+ }
+
+}
+
+class lessc_formatter_classic {
+ public $indentChar = " ";
+
+ public $break = "\n";
+ public $open = " {";
+ public $close = "}";
+ public $selectorSeparator = ", ";
+ public $assignSeparator = ":";
+
+ public $openSingle = " { ";
+ public $closeSingle = " }";
+
+ public $disableSingle = false;
+ public $breakSelectors = false;
+
+ public $compressColors = false;
+
+ public function __construct() {
+ $this->indentLevel = 0;
+ }
+
+ public function indentStr($n = 0) {
+ return str_repeat($this->indentChar, max($this->indentLevel + $n, 0));
+ }
+
+ public function property($name, $value) {
+ return $name . $this->assignSeparator . $value . ";";
+ }
+
+ protected function isEmpty($block) {
+ if (empty($block->lines)) {
+ foreach ($block->children as $child) {
+ if (!$this->isEmpty($child)) return false;
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ public function block($block) {
+ if ($this->isEmpty($block)) return;
+
+ $inner = $pre = $this->indentStr();
+
+ $isSingle = !$this->disableSingle &&
+ is_null($block->type) && count($block->lines) == 1;
+
+ if (!empty($block->selectors)) {
+ $this->indentLevel++;
+
+ if ($this->breakSelectors) {
+ $selectorSeparator = $this->selectorSeparator . $this->break . $pre;
+ } else {
+ $selectorSeparator = $this->selectorSeparator;
+ }
+
+ echo $pre .
+ implode($selectorSeparator, $block->selectors);
+ if ($isSingle) {
+ echo $this->openSingle;
+ $inner = "";
+ } else {
+ echo $this->open . $this->break;
+ $inner = $this->indentStr();
+ }
+
+ }
+
+ if (!empty($block->lines)) {
+ $glue = $this->break.$inner;
+ echo $inner . implode($glue, $block->lines);
+ if (!$isSingle && !empty($block->children)) {
+ echo $this->break;
+ }
+ }
+
+ foreach ($block->children as $child) {
+ $this->block($child);
+ }
+
+ if (!empty($block->selectors)) {
+ if (!$isSingle && empty($block->children)) echo $this->break;
+
+ if ($isSingle) {
+ echo $this->closeSingle . $this->break;
+ } else {
+ echo $pre . $this->close . $this->break;
+ }
+
+ $this->indentLevel--;
+ }
+ }
+}
+
+class lessc_formatter_compressed extends lessc_formatter_classic {
+ public $disableSingle = true;
+ public $open = "{";
+ public $selectorSeparator = ",";
+ public $assignSeparator = ":";
+ public $break = "";
+ public $compressColors = true;
+
+ public function indentStr($n = 0) {
+ return "";
+ }
+}
+
+class lessc_formatter_lessjs extends lessc_formatter_classic {
+ public $disableSingle = true;
+ public $breakSelectors = true;
+ public $assignSeparator = ": ";
+ public $selectorSeparator = ",";
+}
+
+
diff --git a/inc/load.php b/inc/load.php
index 7fb328215..923671296 100644
--- a/inc/load.php
+++ b/inc/load.php
@@ -86,12 +86,13 @@ function load_autoload($name){
'Crypt_Rijndael' => DOKU_INC.'inc/phpseclib/Crypt_Rijndael.php',
'Crypt_AES' => DOKU_INC.'inc/phpseclib/Crypt_AES.php',
'Crypt_Hash' => DOKU_INC.'inc/phpseclib/Crypt_Hash.php',
+ 'lessc' => DOKU_INC.'inc/lessc.inc.php',
'DokuWiki_Action_Plugin' => DOKU_PLUGIN.'action.php',
'DokuWiki_Admin_Plugin' => DOKU_PLUGIN.'admin.php',
'DokuWiki_Syntax_Plugin' => DOKU_PLUGIN.'syntax.php',
'DokuWiki_Remote_Plugin' => DOKU_PLUGIN.'remote.php',
- 'DokuWiki_Auth_Plugin' => DOKU_PLUGIN.'auth.php',
+ 'DokuWiki_Auth_Plugin' => DOKU_PLUGIN.'auth.php',
);
diff --git a/inc/media.php b/inc/media.php
index 5c84bed4b..ee5c0c1eb 100644
--- a/inc/media.php
+++ b/inc/media.php
@@ -1900,7 +1900,7 @@ function media_crop_image($file, $ext, $w, $h=0){
*/
function media_get_token($id,$w,$h){
// token is only required for modified images
- if ($w || $h) {
+ if ($w || $h || media_isexternal($id)) {
$token = $id;
if ($w) $token .= '.'.$w;
if ($h) $token .= '.'.$h;
diff --git a/inc/template.php b/inc/template.php
index bb5f2cd53..ea73b01b6 100644
--- a/inc/template.php
+++ b/inc/template.php
@@ -33,11 +33,13 @@ function template($file) {
* This replaces the deprecated DOKU_TPLINC constant
*
* @author Andreas Gohr <andi@splitbrain.org>
+ * @param string $tpl The template to use, default to current one
* @return string
*/
-function tpl_incdir() {
+function tpl_incdir($tpl='') {
global $conf;
- return DOKU_INC.'lib/tpl/'.$conf['template'].'/';
+ if(!$tpl) $tpl = $conf['template'];
+ return DOKU_INC.'lib/tpl/'.$tpl.'/';
}
/**
@@ -46,10 +48,12 @@ function tpl_incdir() {
* This replaces the deprecated DOKU_TPL constant
*
* @author Andreas Gohr <andi@splitbrain.org>
+ * @param string $tpl The template to use, default to current one
* @return string
*/
-function tpl_basedir() {
+function tpl_basedir($tpl='') {
global $conf;
+ if(!$tpl) $tpl = $conf['template'];
return DOKU_BASE.'lib/tpl/'.$conf['template'].'/';
}
@@ -468,7 +472,7 @@ function tpl_link($url, $name, $more = '', $return = false) {
* @author Andreas Gohr <andi@splitbrain.org>
*/
function tpl_pagelink($id, $name = null) {
- print html_wikilink($id, $name);
+ print '<bdi>'.html_wikilink($id, $name).'</bdi>';
return true;
}
@@ -800,13 +804,7 @@ function tpl_breadcrumbs($sep = '•') {
$crumbs = breadcrumbs(); //setup crumb trace
- //reverse crumborder in right-to-left mode, add RLM character to fix heb/eng display mixups
- if($lang['direction'] == 'rtl') {
- $crumbs = array_reverse($crumbs, true);
- $crumbs_sep = ' &#8207;<span class="bcsep">'.$sep.'</span>&#8207; ';
- } else {
- $crumbs_sep = ' <span class="bcsep">'.$sep.'</span> ';
- }
+ $crumbs_sep = ' <span class="bcsep">'.$sep.'</span> ';
//render crumbs, highlight the last one
print '<span class="bchead">'.$lang['breadcrumb'].':</span>';
@@ -816,7 +814,9 @@ function tpl_breadcrumbs($sep = '•') {
$i++;
echo $crumbs_sep;
if($i == $last) print '<span class="curid">';
+ print '<bdi>';
tpl_link(wl($id), hsc($name), 'class="breadcrumbs" title="'.$id.'"');
+ print '</bdi>';
if($i == $last) print '</span>';
}
return true;
@@ -889,7 +889,7 @@ function tpl_userinfo() {
global $lang;
global $INFO;
if(isset($_SERVER['REMOTE_USER'])) {
- print $lang['loggedinas'].': '.hsc($INFO['userinfo']['name']).' ('.hsc($_SERVER['REMOTE_USER']).')';
+ print $lang['loggedinas'].': <bdi>'.hsc($INFO['userinfo']['name']).'</bdi> (<bdi>'.hsc($_SERVER['REMOTE_USER']).'</bdi>)';
return true;
}
return false;
@@ -928,14 +928,14 @@ function tpl_pageinfo($ret = false) {
// print it
if($INFO['exists']) {
$out = '';
- $out .= $fn;
+ $out .= '<bdi>'.$fn.'</bdi>';
$out .= ' · ';
$out .= $lang['lastmod'];
$out .= ': ';
$out .= $date;
if($INFO['editor']) {
$out .= ' '.$lang['by'].' ';
- $out .= editorinfo($INFO['editor']);
+ $out .= '<bdi>'.editorinfo($INFO['editor']).'</bdi>';
} else {
$out .= ' ('.$lang['external_edit'].')';
}
@@ -943,7 +943,7 @@ function tpl_pageinfo($ret = false) {
$out .= ' · ';
$out .= $lang['lockedby'];
$out .= ': ';
- $out .= editorinfo($INFO['locked']);
+ $out .= '<bdi>'.editorinfo($INFO['locked']).'</bdi>';
}
if($ret) {
return $out;
@@ -1193,6 +1193,34 @@ function tpl_getLang($id) {
}
/**
+ * Retrieve a language dependent file and pass to xhtml renderer for display
+ * template equivalent of p_locale_xhtml()
+ *
+ * @param string $id id of language dependent wiki page
+ * @return string parsed contents of the wiki page in xhtml format
+ */
+function tpl_locale_xhtml($id) {
+ return p_cached_output(tpl_localeFN($id));
+}
+
+/**
+ * Prepends appropriate path for a language dependent filename
+ */
+function tpl_localeFN($id) {
+ $path = tpl_incdir().'lang/';
+ global $conf;
+ $file = DOKU_CONF.'/template_lang/'.$conf['template'].'/'.$conf['lang'].'/'.$id.'.txt';
+ if (!@file_exists($file)){
+ $file = $path.$conf['lang'].'/'.$id.'.txt';
+ if(!@file_exists($file)){
+ //fall back to english
+ $file = $path.'en/'.$id.'.txt';
+ }
+ }
+ return $file;
+}
+
+/**
* prints the "main content" in the mediamanger popup
*
* Depending on the user's actions this may be a list of
@@ -1469,8 +1497,8 @@ function tpl_license($img = 'badge', $imgonly = false, $return = false, $wrap =
}
if(!$imgonly) {
$out .= $lang['license'].' ';
- $out .= '<a href="'.$lic['url'].'" rel="license" class="urlextern"'.$target;
- $out .= '>'.$lic['name'].'</a>';
+ $out .= '<bdi><a href="'.$lic['url'].'" rel="license" class="urlextern"'.$target;
+ $out .= '>'.$lic['name'].'</a></bdi>';
}
if($wrap) $out .= '</div>';
diff --git a/lib/exe/css.php b/lib/exe/css.php
index 768c8eda4..9e1e22e1a 100644
--- a/lib/exe/css.php
+++ b/lib/exe/css.php
@@ -40,43 +40,32 @@ function css_out(){
$type = '';
}
+ // decide from where to get the template
$tpl = trim(preg_replace('/[^\w-]+/','',$INPUT->str('t')));
- if($tpl){
- $tplinc = DOKU_INC.'lib/tpl/'.$tpl.'/';
- $tpldir = DOKU_BASE.'lib/tpl/'.$tpl.'/';
- }else{
- $tplinc = tpl_incdir();
- $tpldir = tpl_basedir();
- }
-
- // used style.ini file
- $styleini = css_styleini($tplinc);
+ if(!$tpl) $tpl = $conf['template'];
// The generated script depends on some dynamic options
- $cache = new cache('styles'.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'].DOKU_BASE.$tplinc.$type,'.css');
+ $cache = new cache('styles'.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'].DOKU_BASE.$tpl.$type,'.css');
- // load template styles
- $tplstyles = array();
- if ($styleini) {
- foreach($styleini['stylesheets'] as $file => $mode) {
- $tplstyles[$mode][$tplinc.$file] = $tpldir;
- }
- }
+ // load styl.ini
+ $styleini = css_styleini($tpl);
// if old 'default' userstyle setting exists, make it 'screen' userstyle for backwards compatibility
if (isset($config_cascade['userstyle']['default'])) {
$config_cascade['userstyle']['screen'] = $config_cascade['userstyle']['default'];
}
- // Array of needed files and their web locations, the latter ones
- // are needed to fix relative paths in the stylesheets
- $files = array();
-
+ // cache influencers
+ $tplinc = tpl_basedir($tpl);
$cache_files = getConfigFiles('main');
$cache_files[] = $tplinc.'style.ini';
- $cache_files[] = $tplinc.'style.local.ini';
+ $cache_files[] = $tplinc.'style.local.ini'; // @deprecated
+ $cache_files[] = DOKU_CONF."tpl/$tpl/style.ini";
$cache_files[] = __FILE__;
+ // Array of needed files and their web locations, the latter ones
+ // are needed to fix relative paths in the stylesheets
+ $files = array();
foreach($mediatypes as $mediatype) {
$files[$mediatype] = array();
// load core styles
@@ -88,8 +77,8 @@ function css_out(){
// load plugin styles
$files[$mediatype] = array_merge($files[$mediatype], css_pluginstyles($mediatype));
// load template styles
- if (isset($tplstyles[$mediatype])) {
- $files[$mediatype] = array_merge($files[$mediatype], $tplstyles[$mediatype]);
+ if (isset($styleini['stylesheets'][$mediatype])) {
+ $files[$mediatype] = array_merge($files[$mediatype], $styleini['stylesheets'][$mediatype]);
}
// load user styles
if(isset($config_cascade['userstyle'][$mediatype])){
@@ -101,7 +90,7 @@ function css_out(){
// please use "[dir=rtl]" in any css file in all, screen or print mode instead
if ($mediatype=='screen') {
if($lang['direction'] == 'rtl'){
- if (isset($tplstyles['rtl'])) $files[$mediatype] = array_merge($files[$mediatype], $tplstyles['rtl']);
+ if (isset($styleini['stylesheets']['rtl'])) $files[$mediatype] = array_merge($files[$mediatype], $styleini['stylesheets']['rtl']);
if (isset($config_cascade['userstyle']['rtl'])) $files[$mediatype][$config_cascade['userstyle']['rtl']] = DOKU_BASE;
}
}
@@ -131,6 +120,8 @@ function css_out(){
// load files
$css_content = '';
foreach($files[$mediatype] as $file => $location){
+ $display = str_replace(fullpath(DOKU_INC), '', fullpath($file));
+ $css_content .= "\n/* XXXXXXXXX $display XXXXXXXXX */\n";
$css_content .= css_loadfile($file, $location);
}
switch ($mediatype) {
@@ -152,9 +143,12 @@ function css_out(){
ob_end_clean();
// apply style replacements
- $css = css_applystyle($css,$tplinc);
+ $css = css_applystyle($css, $styleini['replacements']);
+
+ // parse less
+ $css = css_parseless($css);
- // place all @import statements at the top of the file
+ // place all remaining @import statements at the top of the file
$css = css_moveimports($css);
// compress whitespace and comments
@@ -172,40 +166,157 @@ function css_out(){
}
/**
+ * Uses phpless to parse LESS in our CSS
+ *
+ * most of this function is error handling to show a nice useful error when
+ * LESS compilation fails
+ *
+ * @param $css
+ * @return string
+ */
+function css_parseless($css) {
+ $less = new lessc();
+ try {
+ return $less->compile($css);
+ } catch(Exception $e) {
+ // get exception message
+ $msg = str_replace(array("\n", "\r", "'"), array(), $e->getMessage());
+
+ // try to use line number to find affected file
+ if(preg_match('/line: (\d+)$/', $msg, $m)){
+ $msg = substr($msg, 0, -1* strlen($m[0])); //remove useless linenumber
+ $lno = $m[1];
+
+ // walk upwards to last include
+ $lines = explode("\n", $css);
+ for($i=$lno-1; $i>=0; $i--){
+ if(preg_match('/\/(\* XXXXXXXXX )(.*?)( XXXXXXXXX \*)\//', $lines[$i], $m)){
+ // we found it, add info to message
+ $msg .= ' in '.$m[2].' at line '.($lno-$i);
+ break;
+ }
+ }
+ }
+
+ // something went wrong
+ $error = 'A fatal error occured during compilation of the CSS files. '.
+ 'If you recently installed a new plugin or template it '.
+ 'might be broken and you should try disabling it again. ['.$msg.']';
+
+ echo ".dokuwiki:before {
+ content: '$error';
+ background-color: red;
+ display: block;
+ background-color: #fcc;
+ border-color: #ebb;
+ color: #000;
+ padding: 0.5em;
+ }";
+
+ exit;
+ }
+}
+
+/**
* Does placeholder replacements in the style according to
* the ones defined in a templates style.ini file
*
+ * This also adds the ini defined placeholders as less variables
+ * (sans the surrounding __ and with a ini_ prefix)
+ *
* @author Andreas Gohr <andi@splitbrain.org>
*/
-function css_applystyle($css,$tplinc){
- $styleini = css_styleini($tplinc);
-
- if($styleini){
- $css = strtr($css,$styleini['replacements']);
+function css_applystyle($css, $replacements) {
+ // we convert ini replacements to LESS variable names
+ // and build a list of variable: value; pairs
+ $less = '';
+ foreach((array) $replacements as $key => $value) {
+ $lkey = trim($key, '_');
+ $lkey = '@ini_'.$lkey;
+ $less .= "$lkey: $value;\n";
+
+ $replacements[$key] = $lkey;
}
+
+ // we now replace all old ini replacements with LESS variables
+ $css = strtr($css, $replacements);
+
+ // now prepend the list of LESS variables as the very first thing
+ $css = $less.$css;
return $css;
}
/**
- * Get contents of merged style.ini and style.local.ini as an array.
+ * Load style ini contents
*
- * @author Anika Henke <anika@selfthinker.org>
+ * Loads and merges style.ini files from template and config and prepares
+ * the stylesheet modes
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @param string $tpl the used template
+ * @return array with keys 'stylesheets' and 'replacements'
*/
-function css_styleini($tplinc) {
- $styleini = array();
+function css_styleini($tpl) {
+ $stylesheets = array(); // mode, file => base
+ $replacements = array(); // placeholder => value
+
+ // load template's style.ini
+ $incbase = tpl_incdir($tpl);
+ $webbase = tpl_basedir($tpl);
+ $ini = $incbase.'style.ini';
+ if(file_exists($ini)){
+ $data = parse_ini_file($ini, true);
+
+ // stylesheets
+ if(is_array($data['stylesheets'])) foreach($data['stylesheets'] as $file => $mode){
+ $stylesheets[$mode][$incbase.$file] = $webbase;
+ }
+
+ // replacements
+ if(is_array($data['replacements'])){
+ $replacements = array_merge($replacements, $data['replacements']);
+ }
+ }
- foreach (array($tplinc.'style.ini', $tplinc.'style.local.ini') as $ini) {
- $tmp = (@file_exists($ini)) ? parse_ini_file($ini, true) : array();
+ // load template's style.local.ini
+ // @deprecated 2013-08-03
+ $ini = $incbase.'style.local.ini';
+ if(file_exists($ini)){
+ $data = parse_ini_file($ini, true);
- foreach($tmp as $key => $value) {
- if(array_key_exists($key, $styleini) && is_array($value)) {
- $styleini[$key] = array_merge($styleini[$key], $tmp[$key]);
- } else {
- $styleini[$key] = $value;
- }
+ // stylesheets
+ if(is_array($data['stylesheets'])) foreach($data['stylesheets'] as $file => $mode){
+ $stylesheets[$mode][$incbase.$file] = $webbase;
+ }
+
+ // replacements
+ if(is_array($data['replacements'])){
+ $replacements = array_merge($replacements, $data['replacements']);
}
}
- return $styleini;
+
+ // load configs's style.ini
+ $webbase = DOKU_BASE;
+ $ini = DOKU_CONF."tpl/$tpl/style.ini";
+ $incbase = dirname($ini).'/';
+ if(file_exists($ini)){
+ $data = parse_ini_file($ini, true);
+
+ // stylesheets
+ if(is_array($data['stylesheets'])) foreach($data['stylesheets'] as $file => $mode){
+ $stylesheets[$mode][$incbase.$file] = $webbase;
+ }
+
+ // replacements
+ if(is_array($data['replacements'])){
+ $replacements = array_merge($replacements, $data['replacements']);
+ }
+ }
+
+ return array(
+ 'stylesheets' => $stylesheets,
+ 'replacements' => $replacements
+ );
}
/**
@@ -333,9 +444,11 @@ function css_pluginstyles($mediatype='screen'){
$plugins = plugin_list();
foreach ($plugins as $p){
$list[DOKU_PLUGIN."$p/$mediatype.css"] = DOKU_BASE."lib/plugins/$p/";
+ $list[DOKU_PLUGIN."$p/$mediatype.less"] = DOKU_BASE."lib/plugins/$p/";
// alternative for screen.css
if ($mediatype=='screen') {
$list[DOKU_PLUGIN."$p/style.css"] = DOKU_BASE."lib/plugins/$p/";
+ $list[DOKU_PLUGIN."$p/style.less"] = DOKU_BASE."lib/plugins/$p/";
}
// @deprecated 2012-04-09: rtl will cease to be a mode of its own,
// please use "[dir=rtl]" in any css file in all, screen or print mode instead
diff --git a/lib/exe/fetch.php b/lib/exe/fetch.php
index 7a2250373..5967494bf 100644
--- a/lib/exe/fetch.php
+++ b/lib/exe/fetch.php
@@ -60,6 +60,7 @@ if (defined('SIMPLE_TEST')) {
if($evt->advise_before()) {
// redirects
if($data['status'] > 300 && $data['status'] <= 304) {
+ if (defined('SIMPLE_TEST')) return; //TestResponse doesn't recognize redirects
send_redirect($data['statusmessage']);
}
// send any non 200 status
diff --git a/lib/exe/js.php b/lib/exe/js.php
index 06769d895..4b4b598de 100644
--- a/lib/exe/js.php
+++ b/lib/exe/js.php
@@ -96,6 +96,10 @@ function js_out(){
// load JS specific translations
$json = new JSON();
$lang['js']['plugins'] = js_pluginstrings();
+ $templatestrings = js_templatestrings();
+ if(!empty($templatestrings)) {
+ $lang['js']['template'] = $templatestrings;
+ }
echo 'LANG = '.$json->encode($lang['js']).";\n";
// load toolbar
@@ -210,6 +214,21 @@ function js_pluginstrings()
return $pluginstrings;
}
+function js_templatestrings() {
+ global $conf;
+ $templatestrings = array();
+ if (@file_exists(tpl_incdir()."lang/en/lang.php")) {
+ include tpl_incdir()."lang/en/lang.php";
+ }
+ if (isset($conf['lang']) && $conf['lang']!='en' && @file_exists(tpl_incdir()."lang/".$conf['lang']."/lang.php")) {
+ include tpl_incdir()."lang/".$conf['lang']."/lang.php";
+ }
+ if (isset($lang['js'])) {
+ $templatestrings[$conf['template']] = $lang['js'];
+ }
+ return $templatestrings;
+}
+
/**
* Escapes a String to be embedded in a JavaScript call, keeps \n
* as newline
diff --git a/lib/exe/mediamanager.php b/lib/exe/mediamanager.php
index 66e5ddc82..d9e4a6b04 100644
--- a/lib/exe/mediamanager.php
+++ b/lib/exe/mediamanager.php
@@ -29,12 +29,13 @@
$IMG = null;
}
- global $INFO;
+ global $INFO, $JSINFO;
$INFO = !empty($INFO) ? array_merge($INFO, mediainfo()) : mediainfo();
+ $JSINFO = array('id' => '', 'namespace' => '');
$AUTH = $INFO['perm']; // shortcut for historical reasons
- trigger_event('MEDIAMANAGER_STARTED',$tmp=array());
- session_write_close(); //close session
+ trigger_event('MEDIAMANAGER_STARTED',$tmp=array());
+ session_write_close(); //close session
// do not display the manager if user does not have read access
if($AUTH < AUTH_READ && !$fullscreen) {
diff --git a/lib/plugins/acl/admin.php b/lib/plugins/acl/admin.php
index 0d9cd742a..50377da81 100644
--- a/lib/plugins/acl/admin.php
+++ b/lib/plugins/acl/admin.php
@@ -724,7 +724,7 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin {
static $label = 0; //number labels
$ret = '';
- if($ispage && $setperm > AUTH_EDIT) $perm = AUTH_EDIT;
+ if($ispage && $setperm > AUTH_EDIT) $setperm = AUTH_EDIT;
foreach(array(AUTH_NONE,AUTH_READ,AUTH_EDIT,AUTH_CREATE,AUTH_UPLOAD,AUTH_DELETE) as $perm){
$label += 1;
diff --git a/lib/plugins/acl/lang/nl/lang.php b/lib/plugins/acl/lang/nl/lang.php
index 567eb46dc..e3a95e779 100644
--- a/lib/plugins/acl/lang/nl/lang.php
+++ b/lib/plugins/acl/lang/nl/lang.php
@@ -1,8 +1,8 @@
<?php
+
/**
- * dutch language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author François Kooman <fkooman.tuxed.net>
* @author Jack van Klaren <dokuwiki@afentoe.xs4all.nl>
* @author Riny Heijdendael <riny@heijdendael.nl>
diff --git a/lib/plugins/acl/lang/sv/lang.php b/lib/plugins/acl/lang/sv/lang.php
index 388672fc0..f226542e6 100644
--- a/lib/plugins/acl/lang/sv/lang.php
+++ b/lib/plugins/acl/lang/sv/lang.php
@@ -1,11 +1,11 @@
<?php
+
/**
- * swedish language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Per Foreby <per@foreby.se>
* @author Nicklas Henriksson <nicklas[at]nihe.se>
- * @author Håkan Sandell <hakan.sandell[at]mydata.se>
+ * @author Håkan Sandell <hakan.sandell@home.se>
* @author Dennis Karlsson
* @author Tormod Otter Johansson <tormod@latast.se>
* @author emil@sys.nu
@@ -14,7 +14,6 @@
* @author Emil Lind <emil@sys.nu>
* @author Bogge Bogge <bogge@bogge.com>
* @author Peter Åström <eaustreum@gmail.com>
- * @author Håkan Sandell <hakan.sandell@home.se>
* @author mikael@mallander.net
* @author Smorkster Andersson smorkster@gmail.com
*/
diff --git a/lib/plugins/auth.php b/lib/plugins/auth.php
index ec8ed7e58..dc66d6380 100644
--- a/lib/plugins/auth.php
+++ b/lib/plugins/auth.php
@@ -55,6 +55,18 @@ class DokuWiki_Auth_Plugin extends DokuWiki_Plugin {
}
/**
+ * Available Capabilities. [ DO NOT OVERRIDE ]
+ *
+ * For introspection/debugging
+ *
+ * @author Christopher Smith <chris@jalakai.co.uk>
+ * @return array
+ */
+ public function getCapabilities(){
+ return array_keys($this->cando);
+ }
+
+ /**
* Capability check. [ DO NOT OVERRIDE ]
*
* Checks the capabilities set in the $this->cando array and
diff --git a/lib/plugins/authad/lang/nl/settings.php b/lib/plugins/authad/lang/nl/settings.php
index 933566d18..8f5c84043 100644
--- a/lib/plugins/authad/lang/nl/settings.php
+++ b/lib/plugins/authad/lang/nl/settings.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Dutch language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
*/
$lang['account_suffix'] = 'Je account domeinnaam. Bijv <code>@mijn.domein.org</code>';
$lang['base_dn'] = 'Je basis DN. Bijv. <code>DC=mijn,DC=domein,DC=org</code>';
diff --git a/lib/plugins/authad/lang/sv/settings.php b/lib/plugins/authad/lang/sv/settings.php
index b1eb1cb96..17eb523a8 100644
--- a/lib/plugins/authad/lang/sv/settings.php
+++ b/lib/plugins/authad/lang/sv/settings.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Swedish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Smorkster Andersson smorkster@gmail.com
*/
$lang['account_suffix'] = 'Ditt konto suffix. T.ex. <code>min.domän.org</code>';
diff --git a/lib/plugins/authldap/lang/en/settings.php b/lib/plugins/authldap/lang/en/settings.php
index e3f385f99..b73166ab2 100644
--- a/lib/plugins/authldap/lang/en/settings.php
+++ b/lib/plugins/authldap/lang/en/settings.php
@@ -20,4 +20,4 @@ $lang['debug'] = 'Display additional debug information on errors';
$lang['deref_o_0'] = 'LDAP_DEREF_NEVER';
$lang['deref_o_1'] = 'LDAP_DEREF_SEARCHING';
$lang['deref_o_2'] = 'LDAP_DEREF_FINDING';
-$lang['deref_o_3'] = 'LDAP_DEREF_ALWAYS'; \ No newline at end of file
+$lang['deref_o_3'] = 'LDAP_DEREF_ALWAYS';
diff --git a/lib/plugins/authldap/lang/nl/settings.php b/lib/plugins/authldap/lang/nl/settings.php
index 274c3b7fc..958bd4d6f 100644
--- a/lib/plugins/authldap/lang/nl/settings.php
+++ b/lib/plugins/authldap/lang/nl/settings.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Dutch language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
*/
$lang['server'] = 'Je LDAP server. Ofwel servernaam (<code>localhost</code>) of volledige URL (<code>ldap://server.tld:389</code>)';
$lang['port'] = 'LDAP server poort als hiervoor geen volledige URL is opgegeven';
diff --git a/lib/plugins/authldap/lang/sv/settings.php b/lib/plugins/authldap/lang/sv/settings.php
index 0fdcad147..68dbccfd0 100644
--- a/lib/plugins/authldap/lang/sv/settings.php
+++ b/lib/plugins/authldap/lang/sv/settings.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Swedish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Smorkster Andersson smorkster@gmail.com
*/
$lang['server'] = 'Din LDAO server. Antingen värdnamn (<code>localhost</code>) eller giltig full URL (<code>ldap://server.tld:389</code>)';
diff --git a/lib/plugins/authmysql/lang/nl/settings.php b/lib/plugins/authmysql/lang/nl/settings.php
index dc85b7eee..39fa32112 100644
--- a/lib/plugins/authmysql/lang/nl/settings.php
+++ b/lib/plugins/authmysql/lang/nl/settings.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Dutch language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
*/
$lang['server'] = 'Je MySQL server';
$lang['user'] = 'MySql gebruikersnaam';
diff --git a/lib/plugins/authmysql/lang/sv/settings.php b/lib/plugins/authmysql/lang/sv/settings.php
index 027c64025..420e443f4 100644
--- a/lib/plugins/authmysql/lang/sv/settings.php
+++ b/lib/plugins/authmysql/lang/sv/settings.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Swedish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Smorkster Andersson smorkster@gmail.com
*/
$lang['server'] = 'Din MySQL server';
diff --git a/lib/plugins/authpgsql/lang/nl/settings.php b/lib/plugins/authpgsql/lang/nl/settings.php
index 4e6c007c6..496017f1c 100644
--- a/lib/plugins/authpgsql/lang/nl/settings.php
+++ b/lib/plugins/authpgsql/lang/nl/settings.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Dutch language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
*/
$lang['server'] = 'Je PostgrSQL server';
$lang['port'] = 'Je PostgreSQL server poort';
diff --git a/lib/plugins/authpgsql/lang/sv/settings.php b/lib/plugins/authpgsql/lang/sv/settings.php
index 27cb2601d..7da2e82c8 100644
--- a/lib/plugins/authpgsql/lang/sv/settings.php
+++ b/lib/plugins/authpgsql/lang/sv/settings.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Swedish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Smorkster Andersson smorkster@gmail.com
*/
$lang['server'] = 'Din PostgreSQL server';
diff --git a/lib/plugins/config/admin.php b/lib/plugins/config/admin.php
index cbe9d336a..29529760c 100644
--- a/lib/plugins/config/admin.php
+++ b/lib/plugins/config/admin.php
@@ -268,7 +268,7 @@ class admin_plugin_config extends DokuWiki_Admin_Plugin {
// fill in the plugin name if missing (should exist for plugins with settings)
if (!isset($this->lang['plugin'.CM_KEYMARKER.$plugin.CM_KEYMARKER.'plugin_settings_name'])) {
$this->lang['plugin'.CM_KEYMARKER.$plugin.CM_KEYMARKER.'plugin_settings_name'] =
- ucwords(str_replace('_', ' ', $plugin)).' '.$this->getLang('_plugin_sufix');
+ ucwords(str_replace('_', ' ', $plugin));
}
}
closedir($dh);
@@ -289,7 +289,7 @@ class admin_plugin_config extends DokuWiki_Admin_Plugin {
// fill in the template name if missing (should exist for templates with settings)
if (!isset($this->lang['tpl'.CM_KEYMARKER.$tpl.CM_KEYMARKER.'template_settings_name'])) {
$this->lang['tpl'.CM_KEYMARKER.$tpl.CM_KEYMARKER.'template_settings_name'] =
- ucwords(str_replace('_', ' ', $tpl)).' '.$this->getLang('_template_sufix');
+ ucwords(str_replace('_', ' ', $tpl));
}
return true;
diff --git a/lib/plugins/config/lang/ar/lang.php b/lib/plugins/config/lang/ar/lang.php
index 11b59dacd..66bb4240f 100644
--- a/lib/plugins/config/lang/ar/lang.php
+++ b/lib/plugins/config/lang/ar/lang.php
@@ -31,8 +31,6 @@ $lang['_media'] = 'اعدادات الوسائط';
$lang['_notifications'] = 'اعدادات التنبيه';
$lang['_advanced'] = 'اعدادات متقدمة';
$lang['_network'] = 'اعدادات الشبكة';
-$lang['_plugin_sufix'] = 'اعدادات الملحقات';
-$lang['_template_sufix'] = 'اعدادات القوالب';
$lang['_msg_setting_undefined'] = 'لا بيانات إعدادات.';
$lang['_msg_setting_no_class'] = 'لا صنف إعدادات.';
$lang['_msg_setting_no_default'] = 'لا قيمة افتراضية.';
diff --git a/lib/plugins/config/lang/bg/lang.php b/lib/plugins/config/lang/bg/lang.php
index 1a370eafe..d0df38cae 100644
--- a/lib/plugins/config/lang/bg/lang.php
+++ b/lib/plugins/config/lang/bg/lang.php
@@ -42,12 +42,6 @@ $lang['_notifications'] = 'Настройки за известяване';
$lang['_syndication'] = 'Настройки на RSS емисиите';
$lang['_advanced'] = 'Допълнителни настройки';
$lang['_network'] = 'Мрежови настройки';
-// The settings group name for plugins and templates can be set with
-// plugin_settings_name and template_settings_name respectively. If one
-// of these lang properties is not set, the group name will be generated
-// from the plugin or template name and the localized suffix.
-$lang['_plugin_sufix'] = ' (приставка)';
-$lang['_template_sufix'] = ' (шаблон)';
/* --- Undefined Setting Messages --- */
$lang['_msg_setting_undefined'] = 'Няма метаданни за настройките.';
diff --git a/lib/plugins/config/lang/ca-valencia/lang.php b/lib/plugins/config/lang/ca-valencia/lang.php
index dd319bdb7..b6ceadd59 100644
--- a/lib/plugins/config/lang/ca-valencia/lang.php
+++ b/lib/plugins/config/lang/ca-valencia/lang.php
@@ -30,8 +30,6 @@ $lang['_links'] = 'Ajusts de vínculs';
$lang['_media'] = 'Ajusts de mijos';
$lang['_advanced'] = 'Ajusts alvançats';
$lang['_network'] = 'Ajusts de ret';
-$lang['_plugin_sufix'] = 'Ajusts de plúgins';
-$lang['_template_sufix'] = '(ajusts de la plantilla)';
$lang['_msg_setting_undefined'] = 'Ajust sense informació.';
$lang['_msg_setting_no_class'] = 'Ajust sense classe.';
$lang['_msg_setting_no_default'] = 'Sense valor predeterminat.';
diff --git a/lib/plugins/config/lang/ca/lang.php b/lib/plugins/config/lang/ca/lang.php
index 6de8caf02..a53a859a0 100644
--- a/lib/plugins/config/lang/ca/lang.php
+++ b/lib/plugins/config/lang/ca/lang.php
@@ -33,8 +33,6 @@ $lang['_notifications'] = 'Paràmetres de notificació';
$lang['_syndication'] = 'Paràmetres de sindicació';
$lang['_advanced'] = 'Paràmetres avançats';
$lang['_network'] = 'Paràmetres de xarxa';
-$lang['_plugin_sufix'] = 'Paràmetres de connectors';
-$lang['_template_sufix'] = 'Paràmetres de plantilla';
$lang['_msg_setting_undefined'] = 'Falten metadades de paràmetre.';
$lang['_msg_setting_no_class'] = 'Falta classe de paràmetre.';
$lang['_msg_setting_no_default'] = 'No hi ha valor per defecte.';
diff --git a/lib/plugins/config/lang/cs/lang.php b/lib/plugins/config/lang/cs/lang.php
index 921abb54a..289c458e5 100644
--- a/lib/plugins/config/lang/cs/lang.php
+++ b/lib/plugins/config/lang/cs/lang.php
@@ -42,8 +42,6 @@ $lang['_notifications'] = 'Nastavení upozornění';
$lang['_syndication'] = 'Nastavení syndikace';
$lang['_advanced'] = 'Pokročilá nastavení';
$lang['_network'] = 'Nastavení sítě';
-$lang['_plugin_sufix'] = 'Nastavení pluginů ';
-$lang['_template_sufix'] = 'Nastavení šablon';
$lang['_msg_setting_undefined'] = 'Chybí metadata položky.';
$lang['_msg_setting_no_class'] = 'Chybí třída položky.';
$lang['_msg_setting_no_default'] = 'Chybí výchozí hodnota položky.';
diff --git a/lib/plugins/config/lang/da/lang.php b/lib/plugins/config/lang/da/lang.php
index 79d8dc852..59a602ee5 100644
--- a/lib/plugins/config/lang/da/lang.php
+++ b/lib/plugins/config/lang/da/lang.php
@@ -38,8 +38,6 @@ $lang['_media'] = 'Medieindstillinger';
$lang['_notifications'] = 'Notificeringsindstillinger';
$lang['_advanced'] = 'Avancerede indstillinger';
$lang['_network'] = 'Netværksindstillinger';
-$lang['_plugin_sufix'] = 'Udvidelsesindstillinger';
-$lang['_template_sufix'] = 'Skabelonindstillinger';
$lang['_msg_setting_undefined'] = 'Ingen indstillingsmetadata.';
$lang['_msg_setting_no_class'] = 'Ingen indstillingsklasse.';
$lang['_msg_setting_no_default'] = 'Ingen standardværdi.';
diff --git a/lib/plugins/config/lang/de-informal/lang.php b/lib/plugins/config/lang/de-informal/lang.php
index 262a6332e..598c1a72d 100644
--- a/lib/plugins/config/lang/de-informal/lang.php
+++ b/lib/plugins/config/lang/de-informal/lang.php
@@ -11,6 +11,7 @@
* @author Frank Loizzi <contact@software.bacal.de>
* @author Mateng Schimmerlos <mateng@firemail.de>
* @author Volker Bödker <volker@boedker.de>
+ * @author Matthias Schulte <dokuwiki@lupo49.de>
*/
$lang['menu'] = 'Konfiguration';
$lang['error'] = 'Konfiguration wurde nicht aktualisiert auf Grund eines ungültigen Wertes. Bitte überprüfe deine Änderungen und versuche es erneut.<br />Die/der ungültige(n) Wert(e) werden durch eine rote Umrandung hervorgehoben.';
@@ -20,24 +21,22 @@ $lang['locked'] = 'Die Konfigurationsdatei kann nicht aktualisier
$lang['danger'] = '**Achtung**: Eine Änderung dieser Einstellung kann dein Wiki und das Einstellungsmenü unerreichbar machen.';
$lang['warning'] = 'Achtung: Eine Änderungen dieser Option kann zu unbeabsichtigtem Verhalten führen.';
$lang['security'] = 'Sicherheitswarnung: Eine Änderungen dieser Option können ein Sicherheitsrisiko bedeuten.';
-$lang['_configuration_manager'] = 'Konfiguration';
-$lang['_header_dokuwiki'] = 'DokuWiki-Konfiguration';
-$lang['_header_plugin'] = 'Plugin-Konfiguration';
-$lang['_header_template'] = 'Template-Konfiguration';
+$lang['_configuration_manager'] = 'Konfigurations-Manager';
+$lang['_header_dokuwiki'] = 'DokuWiki';
+$lang['_header_plugin'] = 'Plugin';
+$lang['_header_template'] = 'Template';
$lang['_header_undefined'] = 'Unbekannte Werte';
-$lang['_basic'] = 'Grund-Konfiguration';
-$lang['_display'] = 'Darstellungs-Konfiguration';
-$lang['_authentication'] = 'Authentifizierungs-Konfiguration';
-$lang['_anti_spam'] = 'Anti-Spam-Konfiguration';
-$lang['_editing'] = 'Bearbeitungs-Konfiguration';
-$lang['_links'] = 'Links-Konfiguration';
-$lang['_media'] = 'Medien-Konfiguration';
-$lang['_notifications'] = 'Benachrichtigungs-Konfiguration';
-$lang['_syndication'] = 'Syndication-Konfiguration (RSS)';
-$lang['_advanced'] = 'Erweiterte Konfiguration';
-$lang['_network'] = 'Netzwerk-Konfiguration';
-$lang['_plugin_sufix'] = 'Plugin-Konfiguration';
-$lang['_template_sufix'] = 'Template-Konfiguration';
+$lang['_basic'] = 'Basis';
+$lang['_display'] = 'Darstellung';
+$lang['_authentication'] = 'Authentifizierung';
+$lang['_anti_spam'] = 'Anti-Spam';
+$lang['_editing'] = 'Bearbeitung';
+$lang['_links'] = 'Links';
+$lang['_media'] = 'Medien';
+$lang['_notifications'] = 'Benachrichtigung';
+$lang['_syndication'] = 'Syndication (RSS)';
+$lang['_advanced'] = 'Erweitert';
+$lang['_network'] = 'Netzwerk';
$lang['_msg_setting_undefined'] = 'Keine Konfigurationsmetadaten.';
$lang['_msg_setting_no_class'] = 'Keine Konfigurationsklasse.';
$lang['_msg_setting_no_default'] = 'Kein Standardwert.';
@@ -46,7 +45,7 @@ $lang['start'] = 'Name der Startseite';
$lang['lang'] = 'Sprache';
$lang['template'] = 'Vorlage';
$lang['tagline'] = 'Tag-Linie (nur, wenn vom Template unterstützt)';
-$lang['sidebar'] = 'Name der Sidebar-Seite (nur, wenn vom Template unterstützt)), ein leeres Feld deaktiviert die Sidebar';
+$lang['sidebar'] = 'Name der Sidebar-Seite (nur, wenn vom Template unterstützt), ein leeres Feld deaktiviert die Sidebar';
$lang['license'] = 'Unter welcher Lizenz sollte Ihr Inhalt veröffentlicht werden?';
$lang['savedir'] = 'Ordner zum Speichern von Daten';
$lang['basedir'] = 'Installationsverzeichnis';
diff --git a/lib/plugins/config/lang/de/lang.php b/lib/plugins/config/lang/de/lang.php
index aeadef897..07eb4a750 100644
--- a/lib/plugins/config/lang/de/lang.php
+++ b/lib/plugins/config/lang/de/lang.php
@@ -27,24 +27,22 @@ $lang['locked'] = 'Die Konfigurationsdatei kann nicht geändert w
$lang['danger'] = 'Vorsicht: Die Änderung dieser Option könnte Ihr Wiki und das Konfigurationsmenü unzugänglich machen.';
$lang['warning'] = 'Hinweis: Die Änderung dieser Option könnte unbeabsichtigtes Verhalten hervorrufen.';
$lang['security'] = 'Sicherheitswarnung: Die Änderung dieser Option könnte ein Sicherheitsrisiko darstellen.';
-$lang['_configuration_manager'] = 'Konfiguration';
-$lang['_header_dokuwiki'] = 'DokuWiki-Konfiguration';
-$lang['_header_plugin'] = 'Plugin-Konfiguration';
-$lang['_header_template'] = 'Template-Konfiguration';
+$lang['_configuration_manager'] = 'Konfigurations-Manager';
+$lang['_header_dokuwiki'] = 'DokuWiki';
+$lang['_header_plugin'] = 'Plugin';
+$lang['_header_template'] = 'Template';
$lang['_header_undefined'] = 'Unbekannte Werte';
-$lang['_basic'] = 'Grund-Konfiguration';
-$lang['_display'] = 'Darstellungs-Konfiguration';
-$lang['_authentication'] = 'Authentifizierungs-Konfiguration';
-$lang['_anti_spam'] = 'Anti-Spam-Konfiguration';
-$lang['_editing'] = 'Bearbeitungs-Konfiguration';
-$lang['_links'] = 'Links-Konfiguration';
-$lang['_media'] = 'Medien-Konfiguration';
-$lang['_notifications'] = 'Benachrichtigungs-Konfiguration';
-$lang['_syndication'] = 'Syndication-Konfiguration (RSS)';
-$lang['_advanced'] = 'Erweiterte Konfiguration';
-$lang['_network'] = 'Netzwerk-Konfiguration';
-$lang['_plugin_sufix'] = 'Plugin-Konfiguration';
-$lang['_template_sufix'] = 'Template-Konfiguration';
+$lang['_basic'] = 'Basis';
+$lang['_display'] = 'Darstellung';
+$lang['_authentication'] = 'Authentifizierung';
+$lang['_anti_spam'] = 'Anti-Spam';
+$lang['_editing'] = 'Bearbeitung';
+$lang['_links'] = 'Links';
+$lang['_media'] = 'Medien';
+$lang['_notifications'] = 'Benachrichtigung';
+$lang['_syndication'] = 'Syndication (RSS)';
+$lang['_advanced'] = 'Erweitertet';
+$lang['_network'] = 'Netzwerk';
$lang['_msg_setting_undefined'] = 'Keine Konfigurationsmetadaten.';
$lang['_msg_setting_no_class'] = 'Keine Konfigurationsklasse.';
$lang['_msg_setting_no_default'] = 'Kein Standardwert.';
@@ -59,7 +57,7 @@ $lang['start'] = 'Startseitenname';
$lang['title'] = 'Titel des Wikis';
$lang['template'] = 'Designvorlage (Template)';
$lang['tagline'] = 'Tag-Linie (nur, wenn vom Template unterstützt)';
-$lang['sidebar'] = 'Name der Sidebar-Seite (nur, wenn vom Template unterstützt)), ein leeres Feld deaktiviert die Sidebar';
+$lang['sidebar'] = 'Name der Sidebar-Seite (nur, wenn vom Template unterstützt), ein leeres Feld deaktiviert die Sidebar';
$lang['license'] = 'Unter welcher Lizenz sollen Ihre Inhalte veröffentlicht werden?';
$lang['fullpath'] = 'Den kompletten Dateipfad im Footer anzeigen';
$lang['recent'] = 'Anzahl der Einträge in der Änderungsliste';
diff --git a/lib/plugins/config/lang/el/lang.php b/lib/plugins/config/lang/el/lang.php
index e766c1a4c..4c24e067e 100644
--- a/lib/plugins/config/lang/el/lang.php
+++ b/lib/plugins/config/lang/el/lang.php
@@ -39,8 +39,6 @@ $lang['_notifications'] = 'Ρυθμίσεις ενημερώσεων';
$lang['_syndication'] = 'Ρυθμίσεις σύνδεσης';
$lang['_advanced'] = 'Ρυθμίσεις για Προχωρημένους';
$lang['_network'] = 'Ρυθμίσεις Δικτύου';
-$lang['_plugin_sufix'] = 'Ρυθμίσεις Επεκτάσεων';
-$lang['_template_sufix'] = 'Ρυθμίσεις Προτύπων παρουσίασης';
$lang['_msg_setting_undefined'] = 'Δεν έχουν οριστεί metadata.';
$lang['_msg_setting_no_class'] = 'Δεν έχει οριστεί κλάση.';
$lang['_msg_setting_no_default'] = 'Δεν υπάρχει τιμή εξ ορισμού.';
diff --git a/lib/plugins/config/lang/en/lang.php b/lib/plugins/config/lang/en/lang.php
index 2d012701b..67d3ce51f 100644
--- a/lib/plugins/config/lang/en/lang.php
+++ b/lib/plugins/config/lang/en/lang.php
@@ -4,6 +4,7 @@
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Christopher Smith <chris@jalakai.co.uk>
+ * @author Matthias Schulte <dokuwiki@lupo49.de>
*/
// for admin plugins, the menu prompt to be displayed in the admin menu
@@ -23,29 +24,23 @@ $lang['security'] = 'Security Warning: Changing this option could present a se
/* --- Config Setting Headers --- */
$lang['_configuration_manager'] = 'Configuration Manager'; //same as heading in intro.txt
-$lang['_header_dokuwiki'] = 'DokuWiki Settings';
-$lang['_header_plugin'] = 'Plugin Settings';
-$lang['_header_template'] = 'Template Settings';
+$lang['_header_dokuwiki'] = 'DokuWiki';
+$lang['_header_plugin'] = 'Plugin';
+$lang['_header_template'] = 'Template';
$lang['_header_undefined'] = 'Undefined Settings';
/* --- Config Setting Groups --- */
-$lang['_basic'] = 'Basic Settings';
-$lang['_display'] = 'Display Settings';
-$lang['_authentication'] = 'Authentication Settings';
-$lang['_anti_spam'] = 'Anti-Spam Settings';
-$lang['_editing'] = 'Editing Settings';
-$lang['_links'] = 'Link Settings';
-$lang['_media'] = 'Media Settings';
-$lang['_notifications'] = 'Notification Settings';
-$lang['_syndication'] = 'Syndication Settings';
-$lang['_advanced'] = 'Advanced Settings';
-$lang['_network'] = 'Network Settings';
-// The settings group name for plugins and templates can be set with
-// plugin_settings_name and template_settings_name respectively. If one
-// of these lang properties is not set, the group name will be generated
-// from the plugin or template name and the localized suffix.
-$lang['_plugin_sufix'] = 'Plugin Settings';
-$lang['_template_sufix'] = 'Template Settings';
+$lang['_basic'] = 'Basic';
+$lang['_display'] = 'Display';
+$lang['_authentication'] = 'Authentication';
+$lang['_anti_spam'] = 'Anti-Spam';
+$lang['_editing'] = 'Editing';
+$lang['_links'] = 'Links';
+$lang['_media'] = 'Media';
+$lang['_notifications'] = 'Notification';
+$lang['_syndication'] = 'Syndication (RSS)';
+$lang['_advanced'] = 'Advanced';
+$lang['_network'] = 'Network';
/* --- Undefined Setting Messages --- */
$lang['_msg_setting_undefined'] = 'No setting metadata.';
@@ -104,6 +99,7 @@ $lang['disableactions'] = 'Disable DokuWiki actions';
$lang['disableactions_check'] = 'Check';
$lang['disableactions_subscription'] = 'Subscribe/Unsubscribe';
$lang['disableactions_wikicode'] = 'View source/Export Raw';
+$lang['disableactions_profile_delete'] = 'Delete Own Account';
$lang['disableactions_other'] = 'Other actions (comma separated)';
$lang['auth_security_timeout'] = 'Authentication Security Timeout (seconds)';
$lang['securecookie'] = 'Should cookies set via HTTPS only be sent via HTTPS by the browser? Disable this option when only the login of your wiki is secured with SSL but browsing the wiki is done unsecured.';
diff --git a/lib/plugins/config/lang/eo/lang.php b/lib/plugins/config/lang/eo/lang.php
index b3300c1b5..440d771dc 100644
--- a/lib/plugins/config/lang/eo/lang.php
+++ b/lib/plugins/config/lang/eo/lang.php
@@ -36,8 +36,6 @@ $lang['_notifications'] = 'Sciigaj agordoj';
$lang['_syndication'] = 'Kunhavigaj agordoj';
$lang['_advanced'] = 'Fakaj difinoj';
$lang['_network'] = 'Difinoj por reto';
-$lang['_plugin_sufix'] = 'Difinoj por kromaĵoj';
-$lang['_template_sufix'] = 'Difinoj por ŝablonoj';
$lang['_msg_setting_undefined'] = 'Neniu difinanta metadatumaro.';
$lang['_msg_setting_no_class'] = 'Neniu difinanta klaso.';
$lang['_msg_setting_no_default'] = 'Neniu apriora valoro.';
diff --git a/lib/plugins/config/lang/es/lang.php b/lib/plugins/config/lang/es/lang.php
index 3a2db95b8..847b326a8 100644
--- a/lib/plugins/config/lang/es/lang.php
+++ b/lib/plugins/config/lang/es/lang.php
@@ -49,8 +49,6 @@ $lang['_notifications'] = 'Configuración de notificaciones';
$lang['_syndication'] = 'Configuración de sindicación';
$lang['_advanced'] = 'Parámetros Avanzados';
$lang['_network'] = 'Parámetros de Red';
-$lang['_plugin_sufix'] = 'Parámetros de Plugins';
-$lang['_template_sufix'] = 'Parámetros de Plantillas';
$lang['_msg_setting_undefined'] = 'Sin parámetros de metadata.';
$lang['_msg_setting_no_class'] = 'Sin clase establecida.';
$lang['_msg_setting_no_default'] = 'Sin valor por defecto.';
diff --git a/lib/plugins/config/lang/et/lang.php b/lib/plugins/config/lang/et/lang.php
index 27f2e87ac..cce679f31 100644
--- a/lib/plugins/config/lang/et/lang.php
+++ b/lib/plugins/config/lang/et/lang.php
@@ -16,8 +16,6 @@ $lang['_links'] = 'Lingi seaded';
$lang['_media'] = 'Meedia seaded';
$lang['_advanced'] = 'Laiendatud seaded';
$lang['_network'] = 'Võrgu seaded';
-$lang['_plugin_sufix'] = 'Plugina seaded';
-$lang['_template_sufix'] = 'Kujunduse seaded';
$lang['title'] = 'Wiki pealkiri';
$lang['template'] = 'Kujundus';
$lang['recent'] = 'Viimased muudatused';
diff --git a/lib/plugins/config/lang/eu/lang.php b/lib/plugins/config/lang/eu/lang.php
index 280e57df9..2b67a49ed 100644
--- a/lib/plugins/config/lang/eu/lang.php
+++ b/lib/plugins/config/lang/eu/lang.php
@@ -30,8 +30,6 @@ $lang['_notifications'] = 'Abisuen ezarpenak';
$lang['_syndication'] = 'Sindikazio ezarpenak';
$lang['_advanced'] = 'Ezarpen Aurreratuak';
$lang['_network'] = 'Sare Ezarpenak';
-$lang['_plugin_sufix'] = 'Plugin Ezarpenak';
-$lang['_template_sufix'] = 'Txantiloi Ezarpenak';
$lang['_msg_setting_undefined'] = 'Ezarpen metadaturik ez.';
$lang['_msg_setting_no_class'] = 'Ezarpen klaserik ez.';
$lang['_msg_setting_no_default'] = 'Balio lehenetsirik ez.';
diff --git a/lib/plugins/config/lang/fa/lang.php b/lib/plugins/config/lang/fa/lang.php
index 229fe012e..dd97f716e 100644
--- a/lib/plugins/config/lang/fa/lang.php
+++ b/lib/plugins/config/lang/fa/lang.php
@@ -34,8 +34,6 @@ $lang['_notifications'] = 'تنظیمات آگاه سازی';
$lang['_syndication'] = 'تنظیمات پیوند';
$lang['_advanced'] = 'تنظیمات پیشرفته';
$lang['_network'] = 'تنظیمات شبکه';
-$lang['_plugin_sufix'] = 'تنظیمات افزونه';
-$lang['_template_sufix'] = 'تنظیمات قالب';
$lang['_msg_setting_undefined'] = 'داده‌نمایی برای تنظیمات وجود ندارد';
$lang['_msg_setting_no_class'] = 'هیچ دسته‌ای برای تنظیمات وجود ندارد.';
$lang['_msg_setting_no_default'] = 'بدون مقدار پیش‌فرض';
diff --git a/lib/plugins/config/lang/fi/lang.php b/lib/plugins/config/lang/fi/lang.php
index a5075d2cf..9fd3fba24 100644
--- a/lib/plugins/config/lang/fi/lang.php
+++ b/lib/plugins/config/lang/fi/lang.php
@@ -33,8 +33,6 @@ $lang['_notifications'] = 'Ilmoitus-asetukset';
$lang['_syndication'] = 'Syöteasetukset';
$lang['_advanced'] = 'Lisäasetukset';
$lang['_network'] = 'Verkkoasetukset';
-$lang['_plugin_sufix'] = 'liitännäisen asetukset';
-$lang['_template_sufix'] = 'Sivumallin asetukset';
$lang['_msg_setting_undefined'] = 'Ei asetusten metadataa.';
$lang['_msg_setting_no_class'] = 'Ei asetusluokkaa.';
$lang['_msg_setting_no_default'] = 'Ei oletusarvoa';
diff --git a/lib/plugins/config/lang/fr/lang.php b/lib/plugins/config/lang/fr/lang.php
index a7b3d5e3b..e92144b22 100644
--- a/lib/plugins/config/lang/fr/lang.php
+++ b/lib/plugins/config/lang/fr/lang.php
@@ -46,8 +46,6 @@ $lang['_notifications'] = 'Paramètres de notification';
$lang['_syndication'] = 'Paramètres de syndication';
$lang['_advanced'] = 'Paramètres avancés';
$lang['_network'] = 'Paramètres réseaux';
-$lang['_plugin_sufix'] = 'Paramètres d\'extension';
-$lang['_template_sufix'] = 'Paramètres de modèle';
$lang['_msg_setting_undefined'] = 'Pas de définition de métadonnées';
$lang['_msg_setting_no_class'] = 'Pas de définition de paramètres.';
$lang['_msg_setting_no_default'] = 'Pas de valeur par défaut.';
diff --git a/lib/plugins/config/lang/gl/lang.php b/lib/plugins/config/lang/gl/lang.php
index 0dafd9271..44942cc7c 100644
--- a/lib/plugins/config/lang/gl/lang.php
+++ b/lib/plugins/config/lang/gl/lang.php
@@ -32,8 +32,6 @@ $lang['_notifications'] = 'Opcións de Notificación';
$lang['_syndication'] = 'Opcións de Sindicación';
$lang['_advanced'] = 'Configuración Avanzada';
$lang['_network'] = 'Configuración de Rede';
-$lang['_plugin_sufix'] = 'Configuración de Extensións';
-$lang['_template_sufix'] = 'Configuración de Sobreplanta';
$lang['_msg_setting_undefined'] = 'Non hai configuración de metadatos.';
$lang['_msg_setting_no_class'] = 'Non hai configuración de clase.';
$lang['_msg_setting_no_default'] = 'Non hai valor predeterminado.';
diff --git a/lib/plugins/config/lang/he/lang.php b/lib/plugins/config/lang/he/lang.php
index 687072764..bddfd90af 100644
--- a/lib/plugins/config/lang/he/lang.php
+++ b/lib/plugins/config/lang/he/lang.php
@@ -30,8 +30,6 @@ $lang['_links'] = 'הגדרות קישורים';
$lang['_media'] = 'הגדרות מדיה';
$lang['_advanced'] = 'הגדרות מתקדמות';
$lang['_network'] = 'הגדרות רשת';
-$lang['_plugin_sufix'] = 'הגדרות תוסף';
-$lang['_template_sufix'] = 'הגדרות תבנית';
$lang['_msg_setting_undefined'] = 'אין מידע-על להגדרה.';
$lang['_msg_setting_no_class'] = 'אין קבוצה להגדרה.';
$lang['_msg_setting_no_default'] = 'אין ערך ברירת מחדל.';
diff --git a/lib/plugins/config/lang/hu/lang.php b/lib/plugins/config/lang/hu/lang.php
index 6c47e09a3..6f774bfac 100644
--- a/lib/plugins/config/lang/hu/lang.php
+++ b/lib/plugins/config/lang/hu/lang.php
@@ -36,8 +36,6 @@ $lang['_notifications'] = 'Értesítési beállítások';
$lang['_syndication'] = 'Hírfolyam beállítások';
$lang['_advanced'] = 'Haladó beállítások';
$lang['_network'] = 'Hálózati beállítások';
-$lang['_plugin_sufix'] = 'Bővítmények beállításai';
-$lang['_template_sufix'] = 'Sablon beállítások';
$lang['_msg_setting_undefined'] = 'Nincs beállított metaadat.';
$lang['_msg_setting_no_class'] = 'Nincs beállított osztály.';
$lang['_msg_setting_no_default'] = 'Nincs alapértelmezett érték.';
diff --git a/lib/plugins/config/lang/ia/lang.php b/lib/plugins/config/lang/ia/lang.php
index 1f4e881bb..c3430030c 100644
--- a/lib/plugins/config/lang/ia/lang.php
+++ b/lib/plugins/config/lang/ia/lang.php
@@ -27,8 +27,6 @@ $lang['_links'] = 'Configurationes de ligamines';
$lang['_media'] = 'Configurationes de multimedia';
$lang['_advanced'] = 'Configurationes avantiate';
$lang['_network'] = 'Configurationes de rete';
-$lang['_plugin_sufix'] = 'Configurationes de plug-ins';
-$lang['_template_sufix'] = 'Configurationes de patronos';
$lang['_msg_setting_undefined'] = 'Nulle metadatos de configuration.';
$lang['_msg_setting_no_class'] = 'Nulle classe de configuration.';
$lang['_msg_setting_no_default'] = 'Nulle valor predefinite.';
diff --git a/lib/plugins/config/lang/is/lang.php b/lib/plugins/config/lang/is/lang.php
index c4905d0f9..a99b39ca2 100644
--- a/lib/plugins/config/lang/is/lang.php
+++ b/lib/plugins/config/lang/is/lang.php
@@ -13,7 +13,6 @@ $lang['nochoice'] = '(engir aðrir valmöguleikar fyrir hendi)';
$lang['_display'] = 'Skjástillingar';
$lang['_anti_spam'] = 'Stillingar gegn ruslpósti';
$lang['_editing'] = 'Útgáfastillingar';
-$lang['_plugin_sufix'] = 'Viðbótstillingar';
$lang['lang'] = 'Tungumál';
$lang['title'] = 'Heiti wikis';
$lang['template'] = 'Mát';
diff --git a/lib/plugins/config/lang/it/lang.php b/lib/plugins/config/lang/it/lang.php
index d2272075a..7a831c8de 100644
--- a/lib/plugins/config/lang/it/lang.php
+++ b/lib/plugins/config/lang/it/lang.php
@@ -42,8 +42,6 @@ $lang['_notifications'] = 'Impostazioni di notifica';
$lang['_syndication'] = 'Impostazioni di collaborazione';
$lang['_advanced'] = 'Impostazioni Avanzate';
$lang['_network'] = 'Impostazioni Rete';
-$lang['_plugin_sufix'] = 'Impostazioni Plugin';
-$lang['_template_sufix'] = 'Impostazioni Modello';
$lang['_msg_setting_undefined'] = 'Nessun metadato definito.';
$lang['_msg_setting_no_class'] = 'Nessuna classe definita.';
$lang['_msg_setting_no_default'] = 'Nessun valore predefinito.';
diff --git a/lib/plugins/config/lang/ja/lang.php b/lib/plugins/config/lang/ja/lang.php
index 15eadf731..e8cf8227b 100644
--- a/lib/plugins/config/lang/ja/lang.php
+++ b/lib/plugins/config/lang/ja/lang.php
@@ -37,8 +37,6 @@ $lang['_notifications'] = '通知設定';
$lang['_syndication'] = 'RSS配信設定';
$lang['_advanced'] = '高度な設定';
$lang['_network'] = 'ネットワーク';
-$lang['_plugin_sufix'] = 'プラグイン設定';
-$lang['_template_sufix'] = 'テンプレート設定';
$lang['_msg_setting_undefined'] = '設定のためのメタデータがありません。';
$lang['_msg_setting_no_class'] = '設定クラスがありません。';
$lang['_msg_setting_no_default'] = '初期値が設定されていません。';
diff --git a/lib/plugins/config/lang/ko/lang.php b/lib/plugins/config/lang/ko/lang.php
index 74fe3d8a0..1aab4731a 100644
--- a/lib/plugins/config/lang/ko/lang.php
+++ b/lib/plugins/config/lang/ko/lang.php
@@ -36,8 +36,6 @@ $lang['_notifications'] = '알림 설정';
$lang['_syndication'] = '신디케이션 설정';
$lang['_advanced'] = '고급 설정';
$lang['_network'] = '네트워크 설정';
-$lang['_plugin_sufix'] = '플러그인 설정';
-$lang['_template_sufix'] = '템플릿 설정';
$lang['_msg_setting_undefined'] = '설정된 메타데이터가 없습니다.';
$lang['_msg_setting_no_class'] = '설정된 클래스가 없습니다.';
$lang['_msg_setting_no_default'] = '기본값이 없습니다.';
diff --git a/lib/plugins/config/lang/la/lang.php b/lib/plugins/config/lang/la/lang.php
index 2aff60753..100f06431 100644
--- a/lib/plugins/config/lang/la/lang.php
+++ b/lib/plugins/config/lang/la/lang.php
@@ -26,8 +26,6 @@ $lang['_links'] = 'Nexi Optiones';
$lang['_media'] = 'Visiuorum Optiones';
$lang['_advanced'] = 'Maiores Optiones';
$lang['_network'] = 'Interretis Optiones';
-$lang['_plugin_sufix'] = 'Addendorum Optiones';
-$lang['_template_sufix'] = 'Vicis Formae Optiones';
$lang['_msg_setting_undefined'] = 'Res codicum sine optionibus.';
$lang['_msg_setting_no_class'] = 'Classes sine optionibus';
$lang['_msg_setting_no_default'] = 'Nihil';
diff --git a/lib/plugins/config/lang/lv/lang.php b/lib/plugins/config/lang/lv/lang.php
index 7fcf0fa45..aa692c1e4 100644
--- a/lib/plugins/config/lang/lv/lang.php
+++ b/lib/plugins/config/lang/lv/lang.php
@@ -29,8 +29,6 @@ $lang['_media'] = 'Mēdiju iestatījumi';
$lang['_notifications'] = 'Brīdinājumu iestatījumi';
$lang['_advanced'] = 'Smalkāka iestatīšana';
$lang['_network'] = 'Tīkla iestatījumi';
-$lang['_plugin_sufix'] = 'moduļa iestatījumi';
-$lang['_template_sufix'] = 'šablona iestatījumi';
$lang['_msg_setting_undefined'] = 'Nav atrodami iestatījumu metadati';
$lang['_msg_setting_no_class'] = 'Nav iestatījumu klases';
$lang['_msg_setting_no_default'] = 'Nav noklusētās vērtības';
diff --git a/lib/plugins/config/lang/mr/lang.php b/lib/plugins/config/lang/mr/lang.php
index deef82690..172c47e4f 100644
--- a/lib/plugins/config/lang/mr/lang.php
+++ b/lib/plugins/config/lang/mr/lang.php
@@ -30,8 +30,6 @@ $lang['_links'] = 'लिंक सेटिंग';
$lang['_media'] = 'दृक्श्राव्य माध्यम सेटिंग';
$lang['_advanced'] = 'सविस्तर सेटिंग';
$lang['_network'] = 'नेटवर्क सेटिंग';
-$lang['_plugin_sufix'] = 'प्लगिन सेटिंग';
-$lang['_template_sufix'] = 'टेम्पलेट ( नमुना ) सेटिंग';
$lang['_msg_setting_undefined'] = 'सेटिंगविषयी उप-डेटा उपलब्ध नाही.';
$lang['_msg_setting_no_class'] = 'सेटिंगचा क्लास उपलब्ध नाही';
$lang['_msg_setting_no_default'] = 'आपोआप किम्मत नाही';
diff --git a/lib/plugins/config/lang/ne/lang.php b/lib/plugins/config/lang/ne/lang.php
index a8b426b9c..ffa7713fa 100644
--- a/lib/plugins/config/lang/ne/lang.php
+++ b/lib/plugins/config/lang/ne/lang.php
@@ -21,8 +21,6 @@ $lang['_links'] = 'लिङ्क सेटिंङ्ग';
$lang['_media'] = 'मिडिया सेटिंङ्ग';
$lang['_advanced'] = 'विशिष्ठ सेटिंङ्ग';
$lang['_network'] = 'सञ्जाल सेटिंङ्ग';
-$lang['_plugin_sufix'] = 'प्लगइन सेटिंङ्ग';
-$lang['_template_sufix'] = 'टेम्प्लेट सेटिंङ्ग';
$lang['_msg_setting_undefined'] = 'सेटिंङ्ग मेटाडाटा नभएको';
$lang['_msg_setting_no_class'] = 'सेटिंङ्ग वर्ग नभएको';
$lang['_msg_setting_no_default'] = 'कुनै पूर्व निर्धारित मान छैन ।';
diff --git a/lib/plugins/config/lang/nl/lang.php b/lib/plugins/config/lang/nl/lang.php
index 9aa17c23d..14c8f9b1e 100644
--- a/lib/plugins/config/lang/nl/lang.php
+++ b/lib/plugins/config/lang/nl/lang.php
@@ -41,8 +41,6 @@ $lang['_notifications'] = 'Meldingsinstellingen';
$lang['_syndication'] = 'Syndication-instellingen';
$lang['_advanced'] = 'Geavanceerde instellingen';
$lang['_network'] = 'Netwerkinstellingen';
-$lang['_plugin_sufix'] = 'Plugin-instellingen';
-$lang['_template_sufix'] = 'Sjabloon-instellingen';
$lang['_msg_setting_undefined'] = 'Geen metadata voor deze instelling.';
$lang['_msg_setting_no_class'] = 'Geen class voor deze instelling.';
$lang['_msg_setting_no_default'] = 'Geen standaard waarde.';
diff --git a/lib/plugins/config/lang/no/lang.php b/lib/plugins/config/lang/no/lang.php
index c049c643a..f048a0fe9 100644
--- a/lib/plugins/config/lang/no/lang.php
+++ b/lib/plugins/config/lang/no/lang.php
@@ -43,8 +43,6 @@ $lang['_links'] = 'Innstillinger for lenker';
$lang['_media'] = 'Innstillinger for mediafiler';
$lang['_advanced'] = 'Avanserte innstillinger';
$lang['_network'] = 'Nettverksinnstillinger';
-$lang['_plugin_sufix'] = '– innstillinger for tillegg';
-$lang['_template_sufix'] = '– innstillinger for mal';
$lang['_msg_setting_undefined'] = 'Ingen innstillingsmetadata';
$lang['_msg_setting_no_class'] = 'Ingen innstillingsklasse';
$lang['_msg_setting_no_default'] = 'Ingen standard verdi';
diff --git a/lib/plugins/config/lang/pl/lang.php b/lib/plugins/config/lang/pl/lang.php
index ede824d75..9a7cc49ba 100644
--- a/lib/plugins/config/lang/pl/lang.php
+++ b/lib/plugins/config/lang/pl/lang.php
@@ -40,8 +40,6 @@ $lang['_notifications'] = 'Ustawienia powiadomień';
$lang['_syndication'] = 'Ustawienia RSS';
$lang['_advanced'] = 'Zaawansowane';
$lang['_network'] = 'Sieć';
-$lang['_plugin_sufix'] = 'Wtyczki';
-$lang['_template_sufix'] = 'Motywy';
$lang['_msg_setting_undefined'] = 'Brak danych o ustawieniu.';
$lang['_msg_setting_no_class'] = 'Brak kategorii ustawień.';
$lang['_msg_setting_no_default'] = 'Brak wartości domyślnej.';
diff --git a/lib/plugins/config/lang/pt-br/lang.php b/lib/plugins/config/lang/pt-br/lang.php
index 85218439a..ee1447b4e 100644
--- a/lib/plugins/config/lang/pt-br/lang.php
+++ b/lib/plugins/config/lang/pt-br/lang.php
@@ -44,8 +44,6 @@ $lang['_notifications'] = 'Configurações de notificação';
$lang['_syndication'] = 'Configurações de sindicância';
$lang['_advanced'] = 'Configurações avançadas';
$lang['_network'] = 'Configurações de rede';
-$lang['_plugin_sufix'] = 'Configurações de plug-ins';
-$lang['_template_sufix'] = 'Configurações do modelo';
$lang['_msg_setting_undefined'] = 'Nenhum metadado configurado.';
$lang['_msg_setting_no_class'] = 'Nenhuma classe definida.';
$lang['_msg_setting_no_default'] = 'Nenhum valor padrão.';
diff --git a/lib/plugins/config/lang/pt/lang.php b/lib/plugins/config/lang/pt/lang.php
index 681ff487f..7a9111c62 100644
--- a/lib/plugins/config/lang/pt/lang.php
+++ b/lib/plugins/config/lang/pt/lang.php
@@ -31,8 +31,6 @@ $lang['_links'] = 'Configuração de Ligações';
$lang['_media'] = 'Configuração de Media';
$lang['_advanced'] = 'Configurações Avançadas';
$lang['_network'] = 'Configuração de Rede';
-$lang['_plugin_sufix'] = 'Configuração dos Plugins';
-$lang['_template_sufix'] = 'Configuração das Templates';
$lang['_msg_setting_undefined'] = 'Nenhum metadado configurado.';
$lang['_msg_setting_no_class'] = 'Nenhuma classe definida.';
$lang['_msg_setting_no_default'] = 'Sem valor por omissão.';
diff --git a/lib/plugins/config/lang/ro/lang.php b/lib/plugins/config/lang/ro/lang.php
index 5e853f7d0..e95c551e7 100644
--- a/lib/plugins/config/lang/ro/lang.php
+++ b/lib/plugins/config/lang/ro/lang.php
@@ -34,8 +34,6 @@ $lang['_links'] = 'Setări Legături';
$lang['_media'] = 'Setări Media';
$lang['_advanced'] = 'Setări Avansate';
$lang['_network'] = 'Setări Reţea';
-$lang['_plugin_sufix'] = 'Setări Plugin-uri';
-$lang['_template_sufix'] = 'Setări Şabloane';
$lang['_msg_setting_undefined'] = 'Nesetat metadata';
$lang['_msg_setting_no_class'] = 'Nesetat class';
$lang['_msg_setting_no_default'] = 'Nici o valoare implicită';
diff --git a/lib/plugins/config/lang/ru/lang.php b/lib/plugins/config/lang/ru/lang.php
index cdafacf8f..596ad4ead 100644
--- a/lib/plugins/config/lang/ru/lang.php
+++ b/lib/plugins/config/lang/ru/lang.php
@@ -43,8 +43,6 @@ $lang['_notifications'] = 'Параметры уведомлений';
$lang['_syndication'] = 'Настройки синдикаций';
$lang['_advanced'] = 'Тонкая настройка';
$lang['_network'] = 'Параметры сети';
-$lang['_plugin_sufix'] = 'Параметры плагина';
-$lang['_template_sufix'] = 'Параметры шаблона';
$lang['_msg_setting_undefined'] = 'Не найдены метаданные настроек.';
$lang['_msg_setting_no_class'] = 'Не найден класс настроек.';
$lang['_msg_setting_no_default'] = 'Не задано значение по умолчанию.';
diff --git a/lib/plugins/config/lang/sk/lang.php b/lib/plugins/config/lang/sk/lang.php
index 23a60db90..46e4081a9 100644
--- a/lib/plugins/config/lang/sk/lang.php
+++ b/lib/plugins/config/lang/sk/lang.php
@@ -31,8 +31,6 @@ $lang['_notifications'] = 'Nastavenie upozornení';
$lang['_syndication'] = 'Nastavenie poskytovania obsahu';
$lang['_advanced'] = 'Rozšírené nastavenia';
$lang['_network'] = 'Nastavenia siete';
-$lang['_plugin_sufix'] = 'Nastavenia plug-inu';
-$lang['_template_sufix'] = 'Nastavenia šablóny';
$lang['_msg_setting_undefined'] = 'Nenastavené metadata.';
$lang['_msg_setting_no_class'] = 'Nenastavená trieda.';
$lang['_msg_setting_no_default'] = 'Žiadna predvolená hodnota.';
diff --git a/lib/plugins/config/lang/sl/lang.php b/lib/plugins/config/lang/sl/lang.php
index dcec62288..fe334db55 100644
--- a/lib/plugins/config/lang/sl/lang.php
+++ b/lib/plugins/config/lang/sl/lang.php
@@ -29,8 +29,6 @@ $lang['_links'] = 'Nastavitve povezav';
$lang['_media'] = 'Predstavne nastavitve';
$lang['_advanced'] = 'Napredne nastavitve';
$lang['_network'] = 'Omrežne nastavitve';
-$lang['_plugin_sufix'] = 'nastavitve';
-$lang['_template_sufix'] = 'nastavitve';
$lang['_msg_setting_undefined'] = 'Ni nastavitvenih metapodatkov.';
$lang['_msg_setting_no_class'] = 'Ni nastavitvenega razreda.';
$lang['_msg_setting_no_default'] = 'Ni privzete vrednosti.';
diff --git a/lib/plugins/config/lang/sq/lang.php b/lib/plugins/config/lang/sq/lang.php
index 972b2894c..a6f30875b 100644
--- a/lib/plugins/config/lang/sq/lang.php
+++ b/lib/plugins/config/lang/sq/lang.php
@@ -27,8 +27,6 @@ $lang['_links'] = 'Kuadrot e Link-eve';
$lang['_media'] = 'Kuadrot e Medias';
$lang['_advanced'] = 'Kuadro të Avancuara';
$lang['_network'] = 'Kuadrot e Rrjetit';
-$lang['_plugin_sufix'] = 'Kuadrot e Plugin-eve';
-$lang['_template_sufix'] = 'Kuadrot e Template-eve';
$lang['_msg_setting_undefined'] = 'Metadata pa kuadro.';
$lang['_msg_setting_no_class'] = 'Klasë pa kuadro.';
$lang['_msg_setting_no_default'] = 'Asnjë vlerë default.';
diff --git a/lib/plugins/config/lang/sr/lang.php b/lib/plugins/config/lang/sr/lang.php
index b6d7268aa..1c3250e86 100644
--- a/lib/plugins/config/lang/sr/lang.php
+++ b/lib/plugins/config/lang/sr/lang.php
@@ -28,8 +28,6 @@ $lang['_links'] = 'Подешавања линковања';
$lang['_media'] = 'Подешавања медија';
$lang['_advanced'] = 'Напредна подешавања';
$lang['_network'] = 'Подешавања мреже';
-$lang['_plugin_sufix'] = 'Подешавања за додатке';
-$lang['_template_sufix'] = 'Подешавања за шаблоне';
$lang['_msg_setting_undefined'] = 'Нема метаподатака подешавања';
$lang['_msg_setting_no_class'] = 'Нема класе подешавања';
$lang['_msg_setting_no_default'] = 'Нема подразумеване вредности';
diff --git a/lib/plugins/config/lang/sv/lang.php b/lib/plugins/config/lang/sv/lang.php
index 2a83195d7..74f59502c 100644
--- a/lib/plugins/config/lang/sv/lang.php
+++ b/lib/plugins/config/lang/sv/lang.php
@@ -44,8 +44,6 @@ $lang['_notifications'] = 'Noterings inställningar';
$lang['_syndication'] = 'Syndikats inställningar';
$lang['_advanced'] = 'Avancerade inställningar';
$lang['_network'] = 'Nätverksinställningar';
-$lang['_plugin_sufix'] = '(inställningar för insticksmodul)';
-$lang['_template_sufix'] = '(inställningar för mall)';
$lang['_msg_setting_undefined'] = 'Ingen inställningsmetadata.';
$lang['_msg_setting_no_class'] = 'Ingen inställningsklass.';
$lang['_msg_setting_no_default'] = 'Inget standardvärde.';
diff --git a/lib/plugins/config/lang/th/lang.php b/lib/plugins/config/lang/th/lang.php
index 140a287df..68ee8b8a2 100644
--- a/lib/plugins/config/lang/th/lang.php
+++ b/lib/plugins/config/lang/th/lang.php
@@ -23,7 +23,6 @@ $lang['_links'] = 'การตั้งค่าลิงก์'
$lang['_media'] = 'การตั้งค่าภาพ-เสียง';
$lang['_advanced'] = 'การตั้งค่าขั้นสูง';
$lang['_network'] = 'การตั้งค่าเครือข่าย';
-$lang['_plugin_sufix'] = 'การตั้งค่าโปรแกรมเสริม (plugin)';
$lang['lang'] = 'ภาษา';
$lang['basedir'] = 'ไดเรคทอรีพื้นฐาน';
$lang['baseurl'] = 'URL พื้นฐาน';
diff --git a/lib/plugins/config/lang/tr/lang.php b/lib/plugins/config/lang/tr/lang.php
index 45d70eeb0..cb610f4ff 100644
--- a/lib/plugins/config/lang/tr/lang.php
+++ b/lib/plugins/config/lang/tr/lang.php
@@ -32,8 +32,6 @@ $lang['_links'] = 'Bağlantı Ayarları';
$lang['_media'] = 'Medya Ayarları';
$lang['_advanced'] = 'Gelişmiş Ayarlar';
$lang['_network'] = 'Ağ Ayarları';
-$lang['_plugin_sufix'] = 'Eklenti Ayarları';
-$lang['_template_sufix'] = 'Şablon (Template) Ayarları';
$lang['_msg_setting_undefined'] = 'Ayar üstverisi yok.';
$lang['_msg_setting_no_class'] = 'Ayar sınıfı yok.';
$lang['_msg_setting_no_default'] = 'Varsayılan değer yok.';
diff --git a/lib/plugins/config/lang/uk/lang.php b/lib/plugins/config/lang/uk/lang.php
index c938d911b..dea9203e8 100644
--- a/lib/plugins/config/lang/uk/lang.php
+++ b/lib/plugins/config/lang/uk/lang.php
@@ -36,8 +36,6 @@ $lang['_media'] = 'Налаштування медіа';
$lang['_notifications'] = 'Налаштування сповіщень';
$lang['_advanced'] = 'Розширені налаштування';
$lang['_network'] = 'Налаштування мережі';
-$lang['_plugin_sufix'] = 'Налаштування (доданок)';
-$lang['_template_sufix'] = 'Налаштування (шаблон)';
$lang['_msg_setting_undefined'] = 'Немає метаданих параметру.';
$lang['_msg_setting_no_class'] = 'Немає класу параметру.';
$lang['_msg_setting_no_default'] = 'Немає значення за замовчуванням.';
diff --git a/lib/plugins/config/lang/zh-tw/lang.php b/lib/plugins/config/lang/zh-tw/lang.php
index 7890730a6..cc2c28c31 100644
--- a/lib/plugins/config/lang/zh-tw/lang.php
+++ b/lib/plugins/config/lang/zh-tw/lang.php
@@ -37,8 +37,6 @@ $lang['_notifications'] = '提醒設定';
$lang['_syndication'] = '聚合設定';
$lang['_advanced'] = '進階設定';
$lang['_network'] = '網路設定';
-$lang['_plugin_sufix'] = '附加元件設定';
-$lang['_template_sufix'] = '樣板設定';
$lang['_msg_setting_undefined'] = '設定的後設數據不存在。';
$lang['_msg_setting_no_class'] = '設定的分類不存在。';
$lang['_msg_setting_no_default'] = '無預設值';
diff --git a/lib/plugins/config/lang/zh/lang.php b/lib/plugins/config/lang/zh/lang.php
index 903e987a3..364ad3fe6 100644
--- a/lib/plugins/config/lang/zh/lang.php
+++ b/lib/plugins/config/lang/zh/lang.php
@@ -42,8 +42,6 @@ $lang['_notifications'] = '通知设置';
$lang['_syndication'] = '聚合设置';
$lang['_advanced'] = '高级设置';
$lang['_network'] = '网络设置';
-$lang['_plugin_sufix'] = '插件设置';
-$lang['_template_sufix'] = '模板设置';
$lang['_msg_setting_undefined'] = '设置的元数据不存在。';
$lang['_msg_setting_no_class'] = '设置的分类不存在。';
$lang['_msg_setting_no_default'] = '设置的默认值不存在。';
diff --git a/lib/plugins/config/settings/config.class.php b/lib/plugins/config/settings/config.class.php
index 63be3a726..6d582ad30 100644
--- a/lib/plugins/config/settings/config.class.php
+++ b/lib/plugins/config/settings/config.class.php
@@ -366,12 +366,11 @@ if (!class_exists('setting')) {
var $_pattern = '';
var $_error = false; // only used by those classes which error check
var $_input = null; // only used by those classes which error check
+ var $_caution = null; // used by any setting to provide an alert along with the setting
+ // valid alerts, 'warning', 'danger', 'security'
+ // images matching the alerts are in the plugin's images directory
- var $_cautionList = array(
- 'basedir' => 'danger', 'baseurl' => 'danger', 'savedir' => 'danger', 'cookiedir' => 'danger', 'useacl' => 'danger', 'authtype' => 'danger', 'superuser' => 'danger', 'userewrite' => 'danger',
- 'start' => 'warning', 'camelcase' => 'warning', 'deaccent' => 'warning', 'sepchar' => 'warning', 'compression' => 'warning', 'xsendfile' => 'warning', 'renderer_xhtml' => 'warning', 'fnencode' => 'warning',
- 'allowdebug' => 'security', 'htmlok' => 'security', 'phpok' => 'security', 'iexssprotect' => 'security', 'remote' => 'security', 'fullpath' => 'security'
- );
+ static protected $_validCautions = array('warning','danger','security');
function setting($key, $params=null) {
$this->_key = $key;
@@ -473,8 +472,22 @@ if (!class_exists('setting')) {
function error() { return $this->_error; }
function caution() {
- if (!array_key_exists($this->_key, $this->_cautionList)) return false;
- return $this->_cautionList[$this->_key];
+ if (!empty($this->_caution)) {
+ if (!in_array($this->_caution, setting::$_validCautions)) {
+ trigger_error('Invalid caution string ('.$this->_caution.') in metadata for setting "'.$this->_key.'"', E_USER_WARNING);
+ return false;
+ }
+ return $this->_caution;
+ }
+ // compatibility with previous cautionList
+ // TODO: check if any plugins use; remove
+ if (!empty($this->_cautionList[$this->_key])) {
+ $this->_caution = $this->_cautionList[$this->_key];
+ unset($this->_cautionList);
+
+ return $this->caution();
+ }
+ return false;
}
function _out_key($pretty=false,$url=false) {
@@ -659,10 +672,8 @@ if (!class_exists('setting_password')) {
}
if (!class_exists('setting_email')) {
- if (!defined('SETTING_EMAIL_PATTERN')) define('SETTING_EMAIL_PATTERN','<^'.PREG_PATTERN_VALID_EMAIL.'$>');
class setting_email extends setting_string {
- var $_pattern = SETTING_EMAIL_PATTERN; // no longer required, retained for backward compatibility - FIXME, may not be necessary
var $_multiple = false;
var $_placeholders = false;
@@ -1107,96 +1118,39 @@ if (!class_exists('setting_multicheckbox')) {
}
}
-/**
- * Provide php_strip_whitespace (php5 function) functionality
- *
- * @author Chris Smith <chris@jalakai.co.uk>
- */
-if (!function_exists('php_strip_whitespace')) {
-
- if (function_exists('token_get_all')) {
-
- if (!defined('T_ML_COMMENT')) {
- define('T_ML_COMMENT', T_COMMENT);
- } else {
- define('T_DOC_COMMENT', T_ML_COMMENT);
- }
+if (!class_exists('setting_regex')){
+ class setting_regex extends setting_string {
- /**
- * modified from original
- * source Google Groups, php.general, by David Otton
- */
- function php_strip_whitespace($file) {
- if (!@is_readable($file)) return '';
+ var $_delimiter = '/'; // regex delimiter to be used in testing input
+ var $_pregflags = 'ui'; // regex pattern modifiers to be used in testing input
- $in = join('',@file($file));
- $out = '';
+ /**
+ * update changed setting with user provided value $input
+ * - if changed value fails error check, save it to $this->_input (to allow echoing later)
+ * - if changed value passes error check, set $this->_local to the new value
+ *
+ * @param mixed $input the new value
+ * @return boolean true if changed, false otherwise (incl. on error)
+ */
+ function update($input) {
- $tokens = token_get_all($in);
+ // let parent do basic checks, value, not changed, etc.
+ $local = $this->_local;
+ if (!parent::update($input)) return false;
+ $this->_local = $local;
- foreach ($tokens as $token) {
- if (is_string ($token)) {
- $out .= $token;
- } else {
- list ($id, $text) = $token;
- switch ($id) {
- case T_COMMENT : // fall thru
- case T_ML_COMMENT : // fall thru
- case T_DOC_COMMENT : // fall thru
- case T_WHITESPACE :
- break;
- default : $out .= $text; break;
+ // see if the regex compiles and runs (we don't check for effectiveness)
+ $regex = $this->_delimiter . $input . $this->_delimiter . $this->_pregflags;
+ $lastError = error_get_last();
+ $ok = @preg_match($regex,'testdata');
+ if (preg_last_error() != PREG_NO_ERROR || error_get_last() != $lastError) {
+ $this->_input = $input;
+ $this->_error = true;
+ return false;
}
- }
- }
- return ($out);
- }
-
- } else {
-
- function is_whitespace($c) { return (strpos("\t\n\r ",$c) !== false); }
- function is_quote($c) { return (strpos("\"'",$c) !== false); }
- function is_escaped($s,$i) {
- $idx = $i-1;
- while(($idx>=0) && ($s{$idx} == '\\')) $idx--;
- return (($i - $idx + 1) % 2);
- }
-
- function is_commentopen($str, $i) {
- if ($str{$i} == '#') return "\n";
- if ($str{$i} == '/') {
- if ($str{$i+1} == '/') return "\n";
- if ($str{$i+1} == '*') return "*/";
- }
-
- return false;
- }
-
- function php_strip_whitespace($file) {
-
- if (!@is_readable($file)) return '';
- $contents = join('',@file($file));
- $out = '';
-
- $state = 0;
- for ($i=0; $i<strlen($contents); $i++) {
- if (!$state && is_whitespace($contents{$i})) continue;
-
- if (!$state && ($c_close = is_commentopen($contents, $i))) {
- $c_open_len = ($contents{$i} == '/') ? 2 : 1;
- $i = strpos($contents, $c_close, $i+$c_open_len)+strlen($c_close)-1;
- continue;
- }
-
- $out .= $contents{$i};
- if (is_quote($contents{$i})) {
- if (($state == $contents{$i}) && !is_escaped($contents, $i)) { $state = 0; continue; }
- if (!$state) {$state = $contents{$i}; continue; }
- }
+ $this->_local = $input;
+ return true;
}
-
- return $out;
}
- }
}
diff --git a/lib/plugins/config/settings/config.metadata.php b/lib/plugins/config/settings/config.metadata.php
index 2fb08037d..f4c2ed265 100644
--- a/lib/plugins/config/settings/config.metadata.php
+++ b/lib/plugins/config/settings/config.metadata.php
@@ -34,6 +34,9 @@
* 'array' - a simple (one dimensional) array of string values, shown as comma separated list in the
* config manager but saved as PHP array(). Values may not contain commas themselves.
* _pattern matching on the array values supported.
+ * 'regex' - regular expression string, normally without delimiters; as for string, in addition tested
+ * to see if will compile & run as a regex. in addition to _pattern, also accepts _delimiter
+ * (default '/') and _pregflags (default 'ui')
*
* Single Setting (source: settings/extra.class.php)
* -------------------------------------------------
@@ -43,10 +46,13 @@
* 'im_convert' - as 'setting', input must exist and be an im_convert module
* 'disableactions' - as 'setting'
* 'compression' - no additional parameters. checks php installation supports possible compression alternatives
+ * 'licence' - as multichoice, selection constructed from licence strings in language files
+ * 'renderer' - as multichoice, selection constructed from enabled renderer plugins which canRender()
*
* Any setting commented or missing will use 'setting' class - text input, minimal validation, quoted output
*
* Defined parameters:
+ * '_caution' - no value (default) or 'warning', 'danger', 'security'. display an alert along with the setting
* '_pattern' - string, a preg pattern. input is tested against this pattern before being accepted
* optional all classes, except onoff & multichoice which ignore it
* '_choices' - array of choices. used to populate a selection box. choice will be replaced by a localised
@@ -59,6 +65,9 @@
* '_code' - encoding method to use, accepted values: 'base64','uuencode','plain'. defaults to plain.
* '_min' - minimum numeric value, optional for 'numeric' and 'numericopt', ignored by others
* '_max' - maximum numeric value, optional for 'numeric' and 'numericopt', ignored by others
+ * '_delimiter' - string, default '/', a single character used as a delimiter for testing regex input values
+ * '_pregflags' - string, default 'ui', valid preg pattern modifiers used when testing regex input values, for more
+ * information see http://uk1.php.net/manual/en/reference.pcre.pattern.modifiers.php
* '_multiple' - bool, allow multiple comma separated email values; optional for 'email', ignored by others
*
* @author Chris Smith <chris@jalakai.co.uk>
@@ -83,26 +92,26 @@ $config['heading'] = 'Dokuwiki\'s Main Configuration File - Local Settings';
$meta['_basic'] = array('fieldset');
$meta['title'] = array('string');
-$meta['start'] = array('string','_pattern' => '!^[^:;/]+$!'); // don't accept namespaces
+$meta['start'] = array('string','_caution' => 'warning','_pattern' => '!^[^:;/]+$!'); // don't accept namespaces
$meta['lang'] = array('dirchoice','_dir' => DOKU_INC.'inc/lang/');
$meta['template'] = array('dirchoice','_dir' => DOKU_INC.'lib/tpl/','_pattern' => '/^[\w-]+$/');
$meta['tagline'] = array('string');
$meta['sidebar'] = array('string');
$meta['license'] = array('license');
-$meta['savedir'] = array('savedir');
-$meta['basedir'] = array('string');
-$meta['baseurl'] = array('string');
-$meta['cookiedir'] = array('string');
+$meta['savedir'] = array('savedir','_caution' => 'danger');
+$meta['basedir'] = array('string','_caution' => 'danger');
+$meta['baseurl'] = array('string','_caution' => 'danger');
+$meta['cookiedir'] = array('string','_caution' => 'danger');
$meta['dmode'] = array('numeric','_pattern' => '/0[0-7]{3,4}/'); // only accept octal representation
$meta['fmode'] = array('numeric','_pattern' => '/0[0-7]{3,4}/'); // only accept octal representation
-$meta['allowdebug'] = array('onoff');
+$meta['allowdebug'] = array('onoff','_caution' => 'security');
$meta['_display'] = array('fieldset');
$meta['recent'] = array('numeric');
$meta['recent_days'] = array('numeric');
$meta['breadcrumbs'] = array('numeric','_min' => 0);
$meta['youarehere'] = array('onoff');
-$meta['fullpath'] = array('onoff');
+$meta['fullpath'] = array('onoff','_caution' => 'security');
$meta['typography'] = array('multichoice','_choices' => array(0,1,2));
$meta['dformat'] = array('string');
$meta['signature'] = array('string');
@@ -111,28 +120,28 @@ $meta['toptoclevel'] = array('multichoice','_choices' => array(1,2,3,4,5)); //
$meta['tocminheads'] = array('multichoice','_choices' => array(0,1,2,3,4,5,10,15,20));
$meta['maxtoclevel'] = array('multichoice','_choices' => array(0,1,2,3,4,5));
$meta['maxseclevel'] = array('multichoice','_choices' => array(0,1,2,3,4,5)); // 0 for no sec edit buttons
-$meta['camelcase'] = array('onoff');
-$meta['deaccent'] = array('multichoice','_choices' => array(0,1,2));
+$meta['camelcase'] = array('onoff','_caution' => 'warning');
+$meta['deaccent'] = array('multichoice','_choices' => array(0,1,2),'_caution' => 'warning');
$meta['useheading'] = array('multichoice','_choices' => array(0,'navigation','content',1));
$meta['sneaky_index'] = array('onoff');
-$meta['hidepages'] = array('string');
+$meta['hidepages'] = array('regex');
$meta['_authentication'] = array('fieldset');
-$meta['useacl'] = array('onoff');
+$meta['useacl'] = array('onoff','_caution' => 'danger');
$meta['autopasswd'] = array('onoff');
-$meta['authtype'] = array('authtype');
+$meta['authtype'] = array('authtype','_caution' => 'danger');
$meta['passcrypt'] = array('multichoice','_choices' => array('smd5','md5','apr1','sha1','ssha','lsmd5','crypt','mysql','my411','kmd5','pmd5','hmd5','mediawiki','bcrypt','djangomd5','djangosha1','sha512'));
$meta['defaultgroup']= array('string');
-$meta['superuser'] = array('string');
+$meta['superuser'] = array('string','_caution' => 'danger');
$meta['manager'] = array('string');
$meta['profileconfirm'] = array('onoff');
$meta['rememberme'] = array('onoff');
$meta['disableactions'] = array('disableactions',
- '_choices' => array('backlink','index','recent','revisions','search','subscription','register','resendpwd','profile','edit','wikicode','check'),
+ '_choices' => array('backlink','index','recent','revisions','search','subscription','register','resendpwd','profile','profile_delete','edit','wikicode','check'),
'_combine' => array('subscription' => array('subscribe','unsubscribe'), 'wikicode' => array('source','export_raw')));
$meta['auth_security_timeout'] = array('numeric');
$meta['securecookie'] = array('onoff');
-$meta['remote'] = array('onoff');
+$meta['remote'] = array('onoff','_caution' => 'security');
$meta['remoteuser'] = array('string');
$meta['_anti_spam'] = array('fieldset');
@@ -140,12 +149,12 @@ $meta['usewordblock']= array('onoff');
$meta['relnofollow'] = array('onoff');
$meta['indexdelay'] = array('numeric');
$meta['mailguard'] = array('multichoice','_choices' => array('visible','hex','none'));
-$meta['iexssprotect']= array('onoff');
+$meta['iexssprotect']= array('onoff','_caution' => 'security');
$meta['_editing'] = array('fieldset');
$meta['usedraft'] = array('onoff');
-$meta['htmlok'] = array('onoff');
-$meta['phpok'] = array('onoff');
+$meta['htmlok'] = array('onoff','_caution' => 'security');
+$meta['phpok'] = array('onoff','_caution' => 'security');
$meta['locktime'] = array('numeric');
$meta['cachetime'] = array('numeric');
@@ -184,20 +193,20 @@ $meta['rss_show_summary'] = array('onoff');
$meta['_advanced'] = array('fieldset');
$meta['updatecheck'] = array('onoff');
-$meta['userewrite'] = array('multichoice','_choices' => array(0,1,2));
+$meta['userewrite'] = array('multichoice','_choices' => array(0,1,2),'_caution' => 'danger');
$meta['useslash'] = array('onoff');
-$meta['sepchar'] = array('sepchar');
+$meta['sepchar'] = array('sepchar','_caution' => 'warning');
$meta['canonical'] = array('onoff');
-$meta['fnencode'] = array('multichoice','_choices' => array('url','safe','utf-8'));
+$meta['fnencode'] = array('multichoice','_choices' => array('url','safe','utf-8'),'_caution' => 'warning');
$meta['autoplural'] = array('onoff');
$meta['compress'] = array('onoff');
$meta['cssdatauri'] = array('numeric','_pattern' => '/^\d+$/');
$meta['gzip_output'] = array('onoff');
$meta['send404'] = array('onoff');
-$meta['compression'] = array('compression');
+$meta['compression'] = array('compression','_caution' => 'warning');
$meta['broken_iua'] = array('onoff');
-$meta['xsendfile'] = array('multichoice','_choices' => array(0,1,2,3));
-$meta['renderer_xhtml'] = array('renderer','_format' => 'xhtml','_choices' => array('xhtml'));
+$meta['xsendfile'] = array('multichoice','_choices' => array(0,1,2,3),'_caution' => 'warning');
+$meta['renderer_xhtml'] = array('renderer','_format' => 'xhtml','_choices' => array('xhtml'),'_caution' => 'warning');
$meta['readdircache'] = array('numeric');
$meta['_network'] = array('fieldset');
diff --git a/lib/plugins/plugin/lang/nl/lang.php b/lib/plugins/plugin/lang/nl/lang.php
index 10db78411..1317e44f2 100644
--- a/lib/plugins/plugin/lang/nl/lang.php
+++ b/lib/plugins/plugin/lang/nl/lang.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Dutch language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Wouter Schoot <wouter@schoot.org>
* @author John de Graaff <john@de-graaff.net>
* @author Niels Schoot <niels.schoot@quintiq.com>
diff --git a/lib/plugins/plugin/lang/sv/lang.php b/lib/plugins/plugin/lang/sv/lang.php
index a8578c03c..b7c23743b 100644
--- a/lib/plugins/plugin/lang/sv/lang.php
+++ b/lib/plugins/plugin/lang/sv/lang.php
@@ -1,11 +1,11 @@
<?php
+
/**
- * swedish language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Per Foreby <per@foreby.se>
* @author Nicklas Henriksson <nicklas[at]nihe.se>
- * @author Håkan Sandell <hakan.sandell[at]mydata.se>
+ * @author Håkan Sandell <hakan.sandell@home.se>
* @author Dennis Karlsson
* @author Tormod Otter Johansson <tormod@latast.se>
* @author emil@sys.nu
@@ -14,7 +14,6 @@
* @author Emil Lind <emil@sys.nu>
* @author Bogge Bogge <bogge@bogge.com>
* @author Peter Åström <eaustreum@gmail.com>
- * @author Håkan Sandell <hakan.sandell@home.se>
* @author mikael@mallander.net
* @author Smorkster Andersson smorkster@gmail.com
*/
diff --git a/lib/plugins/popularity/lang/nl/lang.php b/lib/plugins/popularity/lang/nl/lang.php
index b32ad9eb6..dda4a1d7f 100644
--- a/lib/plugins/popularity/lang/nl/lang.php
+++ b/lib/plugins/popularity/lang/nl/lang.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Dutch language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Wouter Schoot <wouter@schoot.org>
* @author Niels Schoot <niels.schoot@quintiq.com>
* @author Dion Nicolaas <dion@nicolaas.net>
diff --git a/lib/plugins/popularity/lang/sv/lang.php b/lib/plugins/popularity/lang/sv/lang.php
index 90d820ba0..942a708c4 100644
--- a/lib/plugins/popularity/lang/sv/lang.php
+++ b/lib/plugins/popularity/lang/sv/lang.php
@@ -1,8 +1,9 @@
<?php
+
/**
- * Swedish language file
- *
- * @author Håkan Sandell <hakan.sandell[at]mydata.se>
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Håkan Sandell <hakan.sandell@home.se>
* @author Dennis Karlsson
* @author Tormod Otter Johansson <tormod@latast.se>
* @author emil@sys.nu
@@ -11,7 +12,6 @@
* @author Emil Lind <emil@sys.nu>
* @author Bogge Bogge <bogge@bogge.com>
* @author Peter Åström <eaustreum@gmail.com>
- * @author Håkan Sandell <hakan.sandell@home.se>
* @author mikael@mallander.net
* @author Smorkster Andersson smorkster@gmail.com
*/
diff --git a/lib/plugins/revert/admin.php b/lib/plugins/revert/admin.php
index ccad6e9de..beff10ced 100644
--- a/lib/plugins/revert/admin.php
+++ b/lib/plugins/revert/admin.php
@@ -128,7 +128,7 @@ class admin_plugin_revert extends DokuWiki_Admin_Plugin {
}
$cnt++;
- $date = strftime($conf['dformat'],$recent['date']);
+ $date = dformat($recent['date']);
echo ($recent['type']===DOKU_CHANGE_TYPE_MINOR_EDIT) ? '<li class="minor">' : '<li>';
echo '<div class="li">';
diff --git a/lib/plugins/revert/lang/de-informal/intro.txt b/lib/plugins/revert/lang/de-informal/intro.txt
index d5a092155..a1733af3a 100644
--- a/lib/plugins/revert/lang/de-informal/intro.txt
+++ b/lib/plugins/revert/lang/de-informal/intro.txt
@@ -1,3 +1,3 @@
-====== Seiten wieder herstellen ======
+====== Seiten wiederherstellen ======
-Dieses Plugin dient der automatischen Wiederherstellung von Seiten nach einem Spam-Angriff. Geben Sie zunächst einen Suchbegriff (z.B. eine Spam URL) ein um eine Liste betroffener Seiten zu erhalten. Nachdem Sie sich vergewissert haben, dass die gefundenen Seiten wirklich Spam enthalten, können Sie die Seiten wieder herstellen.
+Dieses Plugin dient der automatischen Wiederherstellung von Seiten nach einem Spam-Angriff. Gib zunächst einen Suchbegriff (z. B. eine Spam-URL) ein um eine Liste betroffener Seiten zu erhalten. Nachdem du dich vergewissert hast, dass die gefundenen Seiten wirklich Spam enthalten, kannst du die Seiten wiederherstellen.
diff --git a/lib/plugins/revert/lang/de-informal/lang.php b/lib/plugins/revert/lang/de-informal/lang.php
index b702e7727..7ca141e3c 100644
--- a/lib/plugins/revert/lang/de-informal/lang.php
+++ b/lib/plugins/revert/lang/de-informal/lang.php
@@ -10,13 +10,14 @@
* @author Pierre Corell <info@joomla-praxis.de>
* @author Frank Loizzi <contact@software.bacal.de>
* @author Volker Bödker <volker@boedker.de>
+ * @author Matthias Schulte <dokuwiki@lupo49.de>
*/
-$lang['menu'] = 'Zurückstellungsmanager';
+$lang['menu'] = 'Seiten wiederherstellen';
$lang['filter'] = 'Durchsuche als Spam markierte Seiten';
$lang['revert'] = 'Setze ausgewählte Seiten zurück.';
-$lang['reverted'] = '%s zu Revision %s zurückgesetzt';
+$lang['reverted'] = '%s zu Revision %s wiederhergestellt';
$lang['removed'] = '%s entfernt';
-$lang['revstart'] = 'Zurückstellungsprozess gestartet. Dies kann eine längere Zeit dauern. Wenn das Skript vor Fertigstellung stoppt, solltest du es in kleineren Stücken versuchen.';
-$lang['revstop'] = 'Zurückstellungsprozess erfolgreich beendet.';
-$lang['note1'] = 'Beachte: Diese Suche berücksichtigt Gross- und Kleinschreibung';
-$lang['note2'] = 'Beachte: Diese Seite wid zurückgestellt auf die letzte Version, die nicht den Spam-Ausdruck <i>%s</i> enthält.';
+$lang['revstart'] = 'Wiederherstellung gestartet. Dies kann eine längere Zeit dauern. Wenn das Skript vor Fertigstellung stoppt, solltest du es in kleineren Stücken versuchen.';
+$lang['revstop'] = 'Wiederherstellung erfolgreich beendet.';
+$lang['note1'] = 'Beachte: Diese Suche berücksichtigt Groß- und Kleinschreibung';
+$lang['note2'] = 'Beachte: Diese Seite wird wiederhergestellt auf die letzte Version, die nicht den Spam-Begriff <i>%s</i> enthält.';
diff --git a/lib/plugins/revert/lang/de/intro.txt b/lib/plugins/revert/lang/de/intro.txt
index d5a092155..fe74461d9 100644
--- a/lib/plugins/revert/lang/de/intro.txt
+++ b/lib/plugins/revert/lang/de/intro.txt
@@ -1,3 +1,3 @@
-====== Seiten wieder herstellen ======
+====== Seiten wiederherstellen ======
-Dieses Plugin dient der automatischen Wiederherstellung von Seiten nach einem Spam-Angriff. Geben Sie zunächst einen Suchbegriff (z.B. eine Spam URL) ein um eine Liste betroffener Seiten zu erhalten. Nachdem Sie sich vergewissert haben, dass die gefundenen Seiten wirklich Spam enthalten, können Sie die Seiten wieder herstellen.
+Dieses Plugin dient der automatischen Wiederherstellung von Seiten nach einem Spam-Angriff. Geben Sie zunächst einen Suchbegriff (z. B. eine Spam-URL) ein um eine Liste betroffener Seiten zu erhalten. Nachdem Sie sich vergewissert haben, dass die gefundenen Seiten wirklich Spam enthalten, können Sie die Seiten wiederherstellen.
diff --git a/lib/plugins/revert/lang/de/lang.php b/lib/plugins/revert/lang/de/lang.php
index b430ce876..2db065f21 100644
--- a/lib/plugins/revert/lang/de/lang.php
+++ b/lib/plugins/revert/lang/de/lang.php
@@ -1,6 +1,6 @@
<?php
/**
- * Germanlanguage file
+ * German language file
*
* @author Michael Klier <chi@chimeric.de>
* @author Leo Moll <leo@yeasoft.com>
@@ -16,13 +16,14 @@
* @author Christian Wichmann <nospam@zone0.de>
* @author Paul Lachewsky <kaeptn.haddock@gmail.com>
* @author Pierre Corell <info@joomla-praxis.de>
+ * @author Matthias Schulte <dokuwiki@lupo49.de>
*/
-$lang['menu'] = 'Seiten wieder herstellen';
+$lang['menu'] = 'Seiten wiederherstellen';
$lang['filter'] = 'Nach betroffenen Seiten suchen';
-$lang['revert'] = 'Ausgewählte Seiten wieder herstellen';
+$lang['revert'] = 'Ausgewählte Seiten wiederherstellen';
$lang['reverted'] = '%s wieder hergestellt zu Version %s';
$lang['removed'] = '%s entfernt';
$lang['revstart'] = 'Wiederherstellung gestartet. Dies kann einige Zeit dauern. Wenn das Script abbricht, bevor alle Seiten wieder hergestellt wurden, reduzieren Sie die Anzahl der Seiten und wiederholen Sie den Vorgang.';
$lang['revstop'] = 'Wiederherstellung erfolgreich abgeschlossen.';
$lang['note1'] = 'Anmerkung: diese Suche unterscheidet Groß- und Kleinschreibung';
-$lang['note2'] = 'Anmerkung: die Seite wird zur letzten Version, die nicht den angegebenen Spam Begriff <i>%s</i> enthält, wieder hergestellt.';
+$lang['note2'] = 'Anmerkung: die Seite wird wiederhergestellt auf die letzte Version, die nicht den angegebenen Spam Begriff <i>%s</i> enthält.';
diff --git a/lib/plugins/revert/lang/nl/lang.php b/lib/plugins/revert/lang/nl/lang.php
index 0a2880105..882675b81 100644
--- a/lib/plugins/revert/lang/nl/lang.php
+++ b/lib/plugins/revert/lang/nl/lang.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Dutch language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Wouter Schoot <wouter@schoot.org>
* @author John de Graaff <john@de-graaff.net>
* @author Niels Schoot <niels.schoot@quintiq.com>
diff --git a/lib/plugins/revert/lang/sv/lang.php b/lib/plugins/revert/lang/sv/lang.php
index 4a727b339..4a5b944f6 100644
--- a/lib/plugins/revert/lang/sv/lang.php
+++ b/lib/plugins/revert/lang/sv/lang.php
@@ -1,10 +1,11 @@
<?php
+
/**
- * Swedish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Per Foreby <per@foreby.se>
* @author Nicklas Henriksson <nicklas[at]nihe.se>
- * @author Håkan Sandell <hakan.sandell[at]mydata.se>
+ * @author Håkan Sandell <hakan.sandell@home.se>
* @author Dennis Karlsson
* @author Tormod Otter Johansson <tormod@latast.se>
* @author emil@sys.nu
@@ -13,9 +14,9 @@
* @author Emil Lind <emil@sys.nu>
* @author Bogge Bogge <bogge@bogge.com>
* @author Peter Åström <eaustreum@gmail.com>
- * @author Håkan Sandell <hakan.sandell@home.se>
* @author mikael@mallander.net
* @author Smorkster Andersson smorkster@gmail.com
+ * @author Henrik <henrik@idealis.se>
*/
$lang['menu'] = 'Hantera återställningar';
$lang['filter'] = 'Sök efter spamsidor';
diff --git a/lib/plugins/usermanager/admin.php b/lib/plugins/usermanager/admin.php
index ca4c6a650..3c8d38c5e 100644
--- a/lib/plugins/usermanager/admin.php
+++ b/lib/plugins/usermanager/admin.php
@@ -270,7 +270,9 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
$this->_htmlInputField($cmd."_usergroups","usergroups",$this->lang["user_groups"],$groups,$this->_auth->canDo("modGroups"),$indent+6);
if ($this->_auth->canDo("modPass")) {
- $notes[] = $this->lang['note_pass'];
+ if ($cmd == 'add') {
+ $notes[] = $this->lang['note_pass'];
+ }
if ($user) {
$notes[] = $this->lang['note_notify'];
}
@@ -296,11 +298,15 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
ptln(" </tr>",$indent);
ptln(" </tbody>",$indent);
ptln(" </table>",$indent);
- ptln(" </div>",$indent);
-
- foreach ($notes as $note)
- ptln("<div class=\"fn\">".$note."</div>",$indent);
+ if ($notes) {
+ ptln(" <ul class=\"notes\">");
+ foreach ($notes as $note) {
+ ptln(" <li><span class=\"li\">".$note."</span></li>",$indent);
+ }
+ ptln(" </ul>");
+ }
+ ptln(" </div>",$indent);
ptln("</form>",$indent);
}
diff --git a/lib/plugins/usermanager/lang/nl/lang.php b/lib/plugins/usermanager/lang/nl/lang.php
index e960e9a14..e1bf126fb 100644
--- a/lib/plugins/usermanager/lang/nl/lang.php
+++ b/lib/plugins/usermanager/lang/nl/lang.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Dutch language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Wouter Schoot <wouter@schoot.org>
* @author John de Graaff <john@de-graaff.net>
* @author Niels Schoot <niels.schoot@quintiq.com>
diff --git a/lib/plugins/usermanager/lang/sv/lang.php b/lib/plugins/usermanager/lang/sv/lang.php
index f8b530d90..68f5bbc31 100644
--- a/lib/plugins/usermanager/lang/sv/lang.php
+++ b/lib/plugins/usermanager/lang/sv/lang.php
@@ -1,10 +1,11 @@
<?php
+
/**
- * Swedish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Per Foreby <per@foreby.se>
* @author Nicklas Henriksson <nicklas[at]nihe.se>
- * @author Håkan Sandell <hakan.sandell[at]mydata.se>
+ * @author Håkan Sandell <hakan.sandell@home.se>
* @author Dennis Karlsson
* @author Tormod Otter Johansson <tormod@latast.se>
* @author emil@sys.nu
@@ -13,7 +14,6 @@
* @author Emil Lind <emil@sys.nu>
* @author Bogge Bogge <bogge@bogge.com>
* @author Peter Åström <eaustreum@gmail.com>
- * @author Håkan Sandell <hakan.sandell@home.se>
* @author mikael@mallander.net
* @author Smorkster Andersson smorkster@gmail.com
*/
diff --git a/lib/plugins/usermanager/style.css b/lib/plugins/usermanager/style.css
index ff8e5d9d1..506bd7928 100644
--- a/lib/plugins/usermanager/style.css
+++ b/lib/plugins/usermanager/style.css
@@ -13,6 +13,10 @@
#user__manager table {
margin-bottom: 1em;
}
+#user__manager ul.notes {
+ padding-left: 0;
+ padding-right: 1.4em;
+}
#user__manager input.button[disabled] {
color: #ccc!important;
border-color: #ccc!important;
diff --git a/lib/scripts/linkwiz.js b/lib/scripts/linkwiz.js
index c55650d68..875d4a995 100644
--- a/lib/scripts/linkwiz.js
+++ b/lib/scripts/linkwiz.js
@@ -22,6 +22,8 @@ var dw_linkwiz = {
var pos = $editor.position();
// create HTML Structure
+ if(dw_linkwiz.$wiz)
+ return;
dw_linkwiz.$wiz = jQuery(document.createElement('div'))
.dialog({
autoOpen: false,
@@ -235,15 +237,25 @@ var dw_linkwiz = {
link = ':' + link;
}
- var so = link.length+3;
- link = '[['+link+'|';
- if(stxt) {
- link += stxt;
+ var so = link.length;
+ var eo = 0;
+ if(dw_linkwiz.val){
+ if(dw_linkwiz.val.open) {
+ so += dw_linkwiz.val.open.length;
+ link = dw_linkwiz.val.open+link;
+ }
+ if(stxt) {
+ link += '|'+stxt;
+ so += 1;
+ }
+ if(dw_linkwiz.val.close) {
+ link += dw_linkwiz.val.close;
+ eo = dw_linkwiz.val.close.length;
+ }
}
- link += ']]';
- pasteText(sel,link,{startofs: so, endofs: 2});
+ pasteText(sel,link,{startofs: so, endofs: eo});
dw_linkwiz.hide();
// reset the entry to the parent namespace
diff --git a/lib/scripts/toolbar.js b/lib/scripts/toolbar.js
index 5fc4d835e..88cae1e8c 100644
--- a/lib/scripts/toolbar.js
+++ b/lib/scripts/toolbar.js
@@ -217,9 +217,10 @@ function addBtnActionPicker($btn, props, edid) {
* @return boolean If button should be appended
* @author Andreas Gohr <gohr@cosmocode.de>
*/
-function addBtnActionLinkwiz(btn, props, edid) {
+function addBtnActionLinkwiz($btn, props, edid) {
dw_linkwiz.init(jQuery('#'+edid));
- jQuery(btn).click(function(){
+ jQuery($btn).click(function(){
+ dw_linkwiz.val = props;
dw_linkwiz.toggle();
return '';
});
diff --git a/lib/tpl/dokuwiki/css/_admin.css b/lib/tpl/dokuwiki/css/_admin.css
index c8f3694b5..a9518d0ed 100644
--- a/lib/tpl/dokuwiki/css/_admin.css
+++ b/lib/tpl/dokuwiki/css/_admin.css
@@ -50,7 +50,7 @@
.dokuwiki #admin__version {
clear: left;
float: right;
- color: __text_neu__;
+ color: @ini_text_neu;
background-color: inherit;
}
[dir=rtl] .dokuwiki #admin__version {
diff --git a/lib/tpl/dokuwiki/css/_diff.css b/lib/tpl/dokuwiki/css/_diff.css
index 58c24b5c7..b7c82d829 100644
--- a/lib/tpl/dokuwiki/css/_diff.css
+++ b/lib/tpl/dokuwiki/css/_diff.css
@@ -19,7 +19,7 @@
/* table header */
.dokuwiki table.diff th {
- border-bottom: 1px solid __border__;
+ border-bottom: 1px solid @ini_border;
font-size: 110%;
font-weight: normal;
}
diff --git a/lib/tpl/dokuwiki/css/_edit.css b/lib/tpl/dokuwiki/css/_edit.css
index 92ce62126..f40aaa891 100644
--- a/lib/tpl/dokuwiki/css/_edit.css
+++ b/lib/tpl/dokuwiki/css/_edit.css
@@ -16,7 +16,7 @@
}
#draft__status {
float: right;
- color: __text_alt__;
+ color: @ini_text_alt;
background-color: inherit;
}
[dir=rtl] #draft__status {
@@ -35,8 +35,8 @@
/* picker popups (outside of .dokuwiki) */
div.picker {
width: 300px;
- border: 1px solid __border__;
- background-color: __background_alt__;
+ border: 1px solid @ini_border;
+ background-color: @ini_background_alt;
color: inherit;
}
/* picker for headlines */
@@ -106,7 +106,7 @@ div.picker button.toolbutton {
}
/* change background colour if summary is missing */
.dokuwiki .editBar .summary input.missing {
- color: __text__;
+ color: @ini_text;
background-color: #ffcccc;
}
@@ -114,7 +114,7 @@ div.picker button.toolbutton {
********************************************************************/
.dokuwiki div.preview {
- border: dotted __border__;
+ border: dotted @ini_border;
border-width: .2em 0;
padding: 1.4em 0;
margin-bottom: 1.4em;
@@ -138,6 +138,6 @@ div.picker button.toolbutton {
.dokuwiki div.section_highlight {
margin: 0 -1em; /* negative side margin = side padding + side border */
padding: 0 .5em;
- border: solid __background_alt__;
+ border: solid @ini_background_alt;
border-width: 0 .5em;
}
diff --git a/lib/tpl/dokuwiki/css/_fileuploader.css b/lib/tpl/dokuwiki/css/_fileuploader.css
index 42004de28..3c2cd4683 100644
--- a/lib/tpl/dokuwiki/css/_fileuploader.css
+++ b/lib/tpl/dokuwiki/css/_fileuploader.css
@@ -42,8 +42,8 @@
height: 100%;
min-height: 70px;
z-index: 2;
- background: __background_neu__;
- color: __text__;
+ background: @ini_background_neu;
+ color: @ini_text;
text-align: center;
}
@@ -57,7 +57,7 @@
}
.qq-upload-drop-area-active {
- background: __background_alt__;
+ background: @ini_background_alt;
}
/* list of files to upload */
@@ -70,7 +70,7 @@ div.qq-uploader ul {
.qq-uploader li {
margin: 0 0 5px;
- color: __text__;
+ color: @ini_text;
}
.qq-uploader li span,
diff --git a/lib/tpl/dokuwiki/css/_footnotes.css b/lib/tpl/dokuwiki/css/_footnotes.css
index a20f2964e..5d5f7ca30 100644
--- a/lib/tpl/dokuwiki/css/_footnotes.css
+++ b/lib/tpl/dokuwiki/css/_footnotes.css
@@ -16,7 +16,7 @@ div.insitu-footnote {
/*____________ footnotes at the bottom of the page ____________*/
.dokuwiki div.footnotes {
- border-top: 1px solid __border__;
+ border-top: 1px solid @ini_border;
padding: .5em 0 0 0;
margin: 1em 0 0 0;
clear: both;
diff --git a/lib/tpl/dokuwiki/css/_forms.css b/lib/tpl/dokuwiki/css/_forms.css
index 6744750ba..4d3f2b97a 100644
--- a/lib/tpl/dokuwiki/css/_forms.css
+++ b/lib/tpl/dokuwiki/css/_forms.css
@@ -48,7 +48,7 @@
.dokuwiki fieldset {
width: 400px;
text-align: center;
- border: 1px solid __border__;
+ border: 1px solid @ini_border;
padding: 0.5em;
margin: auto;
}
@@ -79,7 +79,10 @@
#dw__register fieldset {
padding-bottom: 0.7em;
}
-
+#dw__profiledelete {
+ display: block;
+ margin-top: 2.8em;
+}
/**
* Styles for the subscription page
diff --git a/lib/tpl/dokuwiki/css/_media_fullscreen.css b/lib/tpl/dokuwiki/css/_media_fullscreen.css
index 8d5e1e8ca..28e347882 100644
--- a/lib/tpl/dokuwiki/css/_media_fullscreen.css
+++ b/lib/tpl/dokuwiki/css/_media_fullscreen.css
@@ -38,7 +38,7 @@
}
#mediamanager__page .panelHeader {
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
margin: 0 10px 10px 0;
padding: 10px 10px 8px;
text-align: left;
@@ -68,7 +68,7 @@
background: transparent url(../../images/resizecol.png) center center no-repeat;
}
#mediamanager__page .ui-resizable-e:hover {
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
}
@@ -99,10 +99,10 @@
margin: 0 0 0 .3em;
border-radius: .5em .5em 0 0;
font-weight: normal;
- background-color: __background_alt__;
- color: __text__;
- border: 1px solid __border__;
- border-bottom-color: __background_alt__;
+ background-color: @ini_background_alt;
+ color: @ini_text;
+ border: 1px solid @ini_border;
+ border-bottom-color: @ini_background_alt;
line-height: 1.4em;
position: relative;
bottom: -1px;
@@ -118,7 +118,7 @@
right: 10px;
}
#mediamanager__page .namespaces .panelHeader {
- border-top: 1px solid __border__;
+ border-top: 1px solid @ini_border;
z-index: 1;
}
@@ -164,7 +164,7 @@
padding: 0;
}
#mediamanager__page .panelHeader ul li {
- color: __text__;
+ color: @ini_text;
float: left;
line-height: 1;
padding-left: 3px;
@@ -205,7 +205,7 @@
}
#mediamanager__page .filelist .panelContent ul li:hover {
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
}
#mediamanager__page .filelist li dt a {
@@ -231,8 +231,8 @@
display: -moz-inline-stack;
/* the right margin should visually be 10px, but because of its inline-block nature the whitespace inbetween is about 4px more */
margin: 0 6px 10px 0;
- background-color: __background_neu__;
- color: __text__;
+ background-color: @ini_background_neu;
+ color: @ini_text;
padding: 5px;
vertical-align: top;
text-align: center;
@@ -287,13 +287,13 @@
max-height: 50px;
margin: 0;
margin-bottom: 3px;
- background-color: __background__;
- color: __text__;
+ background-color: @ini_background;
+ color: @ini_text;
overflow: hidden;
}
#mediamanager__page .filelist .rows li:nth-child(2n+1) {
- background-color: __background_neu__;
+ background-color: @ini_background_neu;
}
#mediamanager__page .filelist .rows li dt {
@@ -372,11 +372,11 @@
#mediamanager__page .file dl dt {
font-weight: bold;
display: block;
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
}
#mediamanager__page .file dl dd {
display: block;
- background-color: __background_neu__;
+ background-color: @ini_background_neu;
}
@@ -415,7 +415,7 @@
#mediamanager__page #page__revisions ul li div.li div {
font-size: 90%;
- color: __text_neu__;
+ color: @ini_text_neu;
padding-left: 18px;
}
@@ -438,7 +438,7 @@
padding: 0;
vertical-align: top;
text-align: left;
- border-color: __background__;
+ border-color: @ini_background;
}
[dir=rtl] #mediamanager__diff td,
[dir=rtl] #mediamanager__diff th {
@@ -447,7 +447,7 @@
#mediamanager__diff th {
font-weight: normal;
- background-color: __background__;
+ background-color: @ini_background;
line-height: 1.2;
}
#mediamanager__diff th a {
@@ -459,7 +459,7 @@
#mediamanager__diff dl dd strong{
background-color: __highlight__;
- color: __text__;
+ color: @ini_text;
font-weight: normal;
}
diff --git a/lib/tpl/dokuwiki/css/_media_popup.css b/lib/tpl/dokuwiki/css/_media_popup.css
index c776e6b8a..1fefd68b6 100644
--- a/lib/tpl/dokuwiki/css/_media_popup.css
+++ b/lib/tpl/dokuwiki/css/_media_popup.css
@@ -20,13 +20,13 @@ html.popup {
overflow: auto;
position: absolute;
left: 0;
- border-right: 1px solid __border__;
+ border-right: 1px solid @ini_border;
}
[dir=rtl] #mediamgr__aside {
left: auto;
right: 0;
border-right-width: 0;
- border-left: 1px solid __border__;
+ border-left: 1px solid @ini_border;
}
#mediamgr__aside .pad {
padding: .5em;
@@ -52,7 +52,7 @@ html.popup {
font-size: 1.5em;
margin-bottom: .5em;
padding-bottom: .2em;
- border-bottom: 1px solid __border__;
+ border-bottom: 1px solid @ini_border;
}
/* left side
@@ -141,13 +141,13 @@ html.popup {
padding: .5em;
}
#media__content .odd {
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
}
#media__content .even {
}
/* highlight newly uploaded or edited file */
#media__content #scroll__here {
- border: 1px dashed __border__;
+ border: 1px dashed @ini_border;
}
/* link which inserts media file */
@@ -167,7 +167,7 @@ html.popup {
/* info how to insert media, if JS disabled */
#media__content div.example {
- color: __text_neu__;
+ color: @ini_text_neu;
margin-left: 1em;
}
diff --git a/lib/tpl/dokuwiki/css/_modal.css b/lib/tpl/dokuwiki/css/_modal.css
index a3d3be194..a46dff30e 100644
--- a/lib/tpl/dokuwiki/css/_modal.css
+++ b/lib/tpl/dokuwiki/css/_modal.css
@@ -18,11 +18,11 @@
}
#link__wiz_result {
- background-color: __background__;
+ background-color: @ini_background;
width: 293px;
height: 193px;
overflow: auto;
- border: 1px solid __border__;
+ border: 1px solid @ini_border;
margin: 3px auto;
text-align: left;
line-height: 1;
@@ -57,16 +57,16 @@
}
#link__wiz_result div.even {
- background-color: __background_neu__;
+ background-color: @ini_background_neu;
}
#link__wiz_result div.selected {
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
}
#link__wiz_result span {
display: block;
- color: __text_neu__;
+ color: @ini_text_neu;
margin-left: 22px;
}
diff --git a/lib/tpl/dokuwiki/css/_search.css b/lib/tpl/dokuwiki/css/_search.css
index 0090308c9..a8972ae72 100644
--- a/lib/tpl/dokuwiki/css/_search.css
+++ b/lib/tpl/dokuwiki/css/_search.css
@@ -44,14 +44,14 @@
}
/* search snippet */
.dokuwiki dl.search_results dd {
- color: __text_alt__;
+ color: @ini_text_alt;
background-color: inherit;
margin: 0 0 1.2em 0;
}
/* search hit in normal text */
.dokuwiki .search_hit {
- color: __text__;
+ color: @ini_text;
background-color: __highlight__;
}
/* search hit in search results */
@@ -60,7 +60,7 @@
}
/* ellipsis separating snippets */
.dokuwiki .search_results .search_sep {
- color: __text__;
+ color: @ini_text;
background-color: inherit;
}
diff --git a/lib/tpl/dokuwiki/css/_tabs.css b/lib/tpl/dokuwiki/css/_tabs.css
index 845ec9a57..860545a27 100644
--- a/lib/tpl/dokuwiki/css/_tabs.css
+++ b/lib/tpl/dokuwiki/css/_tabs.css
@@ -17,7 +17,7 @@
width: 100%;
bottom: 0;
left: 0;
- border-bottom: 1px solid __border__;
+ border-bottom: 1px solid @ini_border;
z-index: 1;
}
@@ -39,9 +39,9 @@
display: inline-block;
padding: .3em .8em;
margin: 0 0 0 .3em;
- background-color: __background_neu__;
- color: __text__;
- border: 1px solid __border__;
+ background-color: @ini_background_neu;
+ color: @ini_text;
+ border: 1px solid @ini_border;
border-radius: .5em .5em 0 0;
position: relative;
z-index: 0;
@@ -68,8 +68,8 @@
.dokuwiki ul.tabs li a:active,
.dokuwiki ul.tabs li a:focus,
.dokuwiki ul.tabs li strong {
- background-color: __background_alt__;
- color: __text__;
+ background-color: @ini_background_alt;
+ color: @ini_text;
text-decoration: none;
font-weight: normal;
}
@@ -78,5 +78,5 @@
.dokuwiki .tabs > ul li .active a,
.dokuwiki ul.tabs li strong {
z-index: 2;
- border-bottom-color: __background_alt__;
+ border-bottom-color: @ini_background_alt;
}
diff --git a/lib/tpl/dokuwiki/css/_toc.css b/lib/tpl/dokuwiki/css/_toc.css
index 1226b5b5b..469e9278c 100644
--- a/lib/tpl/dokuwiki/css/_toc.css
+++ b/lib/tpl/dokuwiki/css/_toc.css
@@ -11,7 +11,7 @@
float: right;
margin: 0 0 1.4em 1.4em;
width: 12em;
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
color: inherit;
}
[dir=rtl] #dw__toc {
diff --git a/lib/tpl/dokuwiki/css/basic.css b/lib/tpl/dokuwiki/css/basic.less
index ef278c939..636923192 100644
--- a/lib/tpl/dokuwiki/css/basic.css
+++ b/lib/tpl/dokuwiki/css/basic.less
@@ -14,8 +14,8 @@ html {
}
html,
body {
- color: __text__;
- background: __background_site__ url(images/page-gradient.png) top left repeat-x;
+ color: @ini_text;
+ background: @ini_background_site url(images/page-gradient.png) top left repeat-x;
margin: 0;
padding: 0;
}
@@ -162,7 +162,7 @@ table {
border-collapse: collapse;
empty-cells: show;
border-spacing: 0;
- border: 1px solid __border__;
+ border: 1px solid @ini_border;
}
caption {
@@ -178,11 +178,11 @@ td {
padding: .3em .5em;
margin: 0;
vertical-align: top;
- border: 1px solid __border__;
+ border: 1px solid @ini_border;
}
th {
font-weight: bold;
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
text-align: left;
}
[dir=rtl] th {
@@ -198,7 +198,7 @@ a {
a:link,
a:visited {
text-decoration: none;
- color: __link__;
+ color: @ini_link;
}
a:link:hover,
a:visited:hover,
@@ -235,8 +235,8 @@ button img {
}
hr {
- border-top: solid __border__;
- border-bottom: solid __background__;
+ border-top: solid @ini_border;
+ border-bottom: solid @ini_background;
border-width: 1px 0;
height: 0;
text-align: center;
@@ -255,7 +255,7 @@ em abbr {
}
mark {
- background-color: __highlight__;
+ background-color: @ini_highlight;
color: inherit;
}
@@ -268,23 +268,23 @@ kbd {
font-size: 1em;
direction: ltr;
text-align: left;
- background-color: __background_site__;
- color: __text__;
- box-shadow: inset 0 0 .3em __border__;
+ background-color: @ini_background_site;
+ color: @ini_text;
+ box-shadow: inset 0 0 .3em @ini_border;
border-radius: 2px;
}
pre {
overflow: auto;
word-wrap: normal;
- border: 1px solid __border__;
+ border: 1px solid @ini_border;
border-radius: 2px;
- box-shadow: inset 0 0 .5em __border__;
+ box-shadow: inset 0 0 .5em @ini_border;
padding: .7em 1em;
}
blockquote {
padding: 0 .5em;
- border: solid __border__;
+ border: solid @ini_border;
border-width: 0 0 0 .25em;
}
[dir=rtl] blockquote {
@@ -323,7 +323,7 @@ form {
fieldset {
padding: .7em 1em 0;
padding: .7rem 1rem; /* for those browsers understanding :last-child */
- border: 1px solid __text_alt__;
+ border: 1px solid @ini_text_alt;
}
fieldset > :last-child {
margin-bottom: 0;
@@ -407,12 +407,8 @@ button,
.qq-upload-button {
color: #333;
background-color: #eee;
- background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPgo8bGluZWFyR3JhZGllbnQgaWQ9Imc4MjQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+CjxzdG9wIHN0b3AtY29sb3I9IiNGRkZGRkYiIG9mZnNldD0iMCIvPjxzdG9wIHN0b3AtY29sb3I9IiNGNEY0RjQiIG9mZnNldD0iMC4zIi8+PHN0b3Agc3RvcC1jb2xvcj0iI0VFRUVFRSIgb2Zmc2V0PSIwLjk5Ii8+PHN0b3Agc3RvcC1jb2xvcj0iI0NDQ0NDQyIgb2Zmc2V0PSIuOTkiLz4KPC9saW5lYXJHcmFkaWVudD4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNnODI0KSIgLz4KPC9zdmc+');
- background: -moz-linear-gradient( top, #ffffff 0%, #f4f4f4 30%, #eeeeee 99%, #cccccc 99%);
- background: -webkit-linear-gradient(top, #ffffff 0%, #f4f4f4 30%, #eeeeee 99%, #cccccc 99%);
- background: -o-linear-gradient( top, #ffffff 0%, #f4f4f4 30%, #eeeeee 99%, #cccccc 99%);
- background: -ms-linear-gradient( top, #ffffff 0%, #f4f4f4 30%, #eeeeee 99%, #cccccc 99%);
- background: linear-gradient( top, #ffffff 0%, #f4f4f4 30%, #eeeeee 99%, #cccccc 99%);
+ background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPgo8bGluZWFyR3JhZGllbnQgaWQ9Imc4MjQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+CjxzdG9wIHN0b3AtY29sb3I9IiNGRkZGRkYiIG9mZnNldD0iMCIvPjxzdG9wIHN0b3AtY29sb3I9IiNGNEY0RjQiIG9mZnNldD0iMC4zIi8+PHN0b3Agc3RvcC1jb2xvcj0iI0VFRUVFRSIgb2Zmc2V0PSIwLjk5Ii8+PHN0b3Agc3RvcC1jb2xvcj0iI0NDQ0NDQyIgb2Zmc2V0PSIuOTkiLz4KPC9saW5lYXJHcmFkaWVudD4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNnODI0KSIgLz4KPC9zdmc+);
+ .linear-gradient("top, #ffffff 0%, #f4f4f4 30%, #eeeeee 99%, #cccccc 99%");
border: 1px solid #ccc;
border-radius: 2px;
padding: .1em .5em;
@@ -445,12 +441,8 @@ button:focus,
.qq-upload-button:hover {
border-color: #999;
background-color: #ddd;
- background-image:url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPgo8bGluZWFyR3JhZGllbnQgaWQ9Imc2NzAiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+CjxzdG9wIHN0b3AtY29sb3I9IiNGRkZGRkYiIG9mZnNldD0iMCIvPjxzdG9wIHN0b3AtY29sb3I9IiNGNEY0RjQiIG9mZnNldD0iMC4zIi8+PHN0b3Agc3RvcC1jb2xvcj0iI0RERERERCIgb2Zmc2V0PSIwLjk5Ii8+PHN0b3Agc3RvcC1jb2xvcj0iI0JCQkJCQiIgb2Zmc2V0PSIuOTkiLz4KPC9saW5lYXJHcmFkaWVudD4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNnNjcwKSIgLz4KPC9zdmc+');
- background: -moz-linear-gradient( top, #ffffff 0%, #f4f4f4 30%, #dddddd 99%, #bbbbbb 99%);
- background: -webkit-linear-gradient(top, #ffffff 0%, #f4f4f4 30%, #dddddd 99%, #bbbbbb 99%);
- background: -o-linear-gradient( top, #ffffff 0%, #f4f4f4 30%, #dddddd 99%, #bbbbbb 99%);
- background: -ms-linear-gradient( top, #ffffff 0%, #f4f4f4 30%, #dddddd 99%, #bbbbbb 99%);
- background: linear-gradient( top, #ffffff 0%, #f4f4f4 30%, #dddddd 99%, #bbbbbb 99%);
+ background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPgo8bGluZWFyR3JhZGllbnQgaWQ9Imc2NzAiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+CjxzdG9wIHN0b3AtY29sb3I9IiNGRkZGRkYiIG9mZnNldD0iMCIvPjxzdG9wIHN0b3AtY29sb3I9IiNGNEY0RjQiIG9mZnNldD0iMC4zIi8+PHN0b3Agc3RvcC1jb2xvcj0iI0RERERERCIgb2Zmc2V0PSIwLjk5Ii8+PHN0b3Agc3RvcC1jb2xvcj0iI0JCQkJCQiIgb2Zmc2V0PSIuOTkiLz4KPC9saW5lYXJHcmFkaWVudD4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNnNjcwKSIgLz4KPC9zdmc+);
+ .linear-gradient("top, #ffffff 0%, #f4f4f4 30%, #dddddd 99%, #bbbbbb 99%");
}
input::-moz-focus-inner,
diff --git a/lib/tpl/dokuwiki/css/content.css b/lib/tpl/dokuwiki/css/content.less
index b1498d4de..56551fe3b 100644
--- a/lib/tpl/dokuwiki/css/content.css
+++ b/lib/tpl/dokuwiki/css/content.less
@@ -32,54 +32,56 @@
*/
/* hx margin-left = (1 / font-size) * .levelx-margin */
-
/*____________ links to wiki pages (addition to _links) ____________*/
/* existing wikipage */
.dokuwiki a.wikilink1 {
- color: __existing__;
+ color: @ini_existing;
background-color: inherit;
}
+
/* not existing wikipage */
.dokuwiki a.wikilink2 {
- color: __missing__;
+ color: @ini_missing;
background-color: inherit;
}
-
/*____________ images ____________*/
/* embedded images (styles are already partly set in lib/styles/all.css) */
.dokuwiki img.media {
margin: .2em 0;
}
+
.dokuwiki img.medialeft {
margin: .2em 1em .2em 0;
}
+
.dokuwiki img.mediaright {
margin: .2em 0 .2em 1em;
}
+
.dokuwiki img.mediacenter {
margin: .2em auto;
}
-
/*____________ lists ____________*/
#dokuwiki__content ul li,
#dokuwiki__aside ul li {
- color: __text_alt__;
+ color: @ini_text_alt;
}
+
#dokuwiki__content ol li,
#dokuwiki__aside ol li {
- color: __text_neu__;
+ color: @ini_text_neu;
}
+
#dokuwiki__content li .li,
#dokuwiki__aside li .li {
- color: __text__;
+ color: @ini_text;
}
-
/*____________ tables ____________*/
/* div around each table */
@@ -87,6 +89,7 @@
overflow-x: auto;
margin-bottom: 1.4em;
}
+
.dokuwiki div.table table {
margin-bottom: 0;
}
@@ -94,14 +97,15 @@
.dokuwiki table.inline {
min-width: 50%;
}
+
.dokuwiki table.inline tr:hover td {
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
}
+
.dokuwiki table.inline tr:hover th {
- background-color: __border__;
+ background-color: @ini_border;
}
-
/*____________ code ____________*/
/* fix if background-color hides underlining */
@@ -116,66 +120,61 @@
/* filenames for downloadable file and code blocks */
.dokuwiki dl.code,
.dokuwiki dl.file {
+ dt {
+ background-color: @ini_background_site;
+ .linear-gradient(~"top, @{ini_background_alt} 0%, @{ini_background_site} 100%");
+ color: inherit;
+ border: 1px solid @ini_border;
+ border-bottom-color: @ini_background_site;
+ border-top-left-radius: .3em;
+ border-top-right-radius: .3em;
+ padding: .3em .6em .1em;
+ margin-bottom: -1px;
+ float: left;
+
+ a {
+ background-color: transparent;
+ font-size: 0.875em;
+ font-weight: normal;
+ display: block;
+ min-height: 16px;
+ }
+ }
+
+ dd {
+ margin: 0;
+ clear: left;
+ min-height: 1px; /* for IE7 */
+ }
+
+ pre {
+ box-shadow: inset -4px -4px .5em -.3em @ini_border;
+ }
+}
+
+[dir=rtl] .dokuwiki dl.code,
+[dir=rtl] .dokuwiki dl.file {
+ dt {
+ float: right;
+ }
+
+ dd {
+ clear: right;
+ }
}
-.dokuwiki dl.code dt,
-.dokuwiki dl.file dt {
- background-color: __background_site__;
- background: -moz-linear-gradient( top, __background_alt__ 0%, __background_site__ 100%);
- background: -webkit-linear-gradient(top, __background_alt__ 0%, __background_site__ 100%);
- background: -o-linear-gradient( top, __background_alt__ 0%, __background_site__ 100%);
- background: -ms-linear-gradient( top, __background_alt__ 0%, __background_site__ 100%);
- background: linear-gradient( top, __background_alt__ 0%, __background_site__ 100%);
- color: inherit;
- border: 1px solid __border__;
- border-bottom-color: __background_site__;
- border-top-left-radius: .3em;
- border-top-right-radius: .3em;
- padding: .3em .6em .1em;
- margin-bottom: -1px;
- float: left;
-}
-[dir=rtl] .dokuwiki dl.code dt,
-[dir=rtl] .dokuwiki dl.file dt {
- float: right;
-}
-.dokuwiki dl.code dt a,
-.dokuwiki dl.file dt a {
- background-color: transparent;
- font-size: 0.875em;
- font-weight: normal;
- display: block;
- min-height: 16px;
-}
-
-.dokuwiki dl.code dd,
-.dokuwiki dl.file dd {
- margin: 0;
- clear: left;
- min-height: 1px; /* for IE7 */
-}
-[dir=rtl] .dokuwiki dl.code dd,
-[dir=rtl] .dokuwiki dl.file dd {
- clear: right;
-}
-
-.dokuwiki dl.code pre,
-.dokuwiki dl.file pre {
- box-shadow: inset -4px -4px .5em -.3em __border__;
-}
-
-
/*____________ JS popup ____________*/
.JSpopup {
- background-color: __background__;
- color: __text__;
- border: 1px solid __border__;
- box-shadow: .1em .1em .1em __border__;
+ background-color: @ini_background;
+ color: @ini_text;
+ border: 1px solid @ini_border;
+ box-shadow: .1em .1em .1em @ini_border;
border-radius: 2px;
padding: .3em .5em;
font-size: .9em;
}
+
.dokuwiki form.search div.ajax_qsearch {
top: -.35em;
font-size: 1em;
@@ -186,12 +185,12 @@
.JSpopup ol {
padding-left: 0;
}
+
[dir=rtl] .JSpopup ul,
[dir=rtl] .JSpopup ol {
padding-right: 0;
}
-
/* changes to underscored CSS files
********************************************************************/
@@ -202,41 +201,49 @@
#dokuwiki__content span.curid a {
font-weight: normal;
}
+
#dokuwiki__content strong span.curid a {
font-weight: bold;
}
-
/*____________ changes to _edit ____________*/
-.dokuwiki div.toolbar button.toolbutton {
- border-radius: 0;
- border-left-width: 0;
- padding: .1em .35em;
-}
-.dokuwiki div.toolbar button.toolbutton:first-child {
- border-top-left-radius: 4px;
- border-bottom-left-radius: 4px;
- border-left-width: 1px;
-}
-[dir=rtl] .dokuwiki div.toolbar button.toolbutton:first-child {
- border-top-left-radius: 0;
- border-bottom-left-radius: 0;
- border-top-right-radius: 4px;
- border-bottom-right-radius: 4px;
- border-left-width: 0;
- border-right-width: 1px;
-}
-.dokuwiki div.toolbar button.toolbutton:last-child {
- border-top-right-radius: 4px;
- border-bottom-right-radius: 4px;
-}
-[dir=rtl] .dokuwiki div.toolbar button.toolbutton:last-child {
- border-top-left-radius: 4px;
- border-bottom-left-radius: 4px;
- border-top-right-radius: 0;
- border-bottom-right-radius: 0;
- border-left-width: 1px;
+.dokuwiki div.toolbar {
+ button.toolbutton {
+ border-radius: 0;
+ border-left-width: 0;
+ padding: .1em .35em;
+ }
+
+ button.toolbutton:first-child {
+ border-top-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+ border-left-width: 1px;
+ }
+
+ button.toolbutton:last-child {
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+ }
+}
+
+[dir=rtl] .dokuwiki div.toolbar {
+ button.toolbutton:last-child {
+ border-top-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ border-left-width: 1px;
+ }
+
+ button.toolbutton:first-child {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+ border-left-width: 0;
+ border-right-width: 1px;
+ }
}
.dokuwiki div.section_highlight {
@@ -253,31 +260,34 @@
margin: 0 -2em;
padding: 0 2em;
}
+
.dokuwiki.hasSidebar div.preview {
- border-right: __sidebar_width__ solid __background_alt__;
+ border-right: @ini_sidebar_width solid @ini_background_alt;
}
+
[dir=rtl] .dokuwiki.hasSidebar div.preview {
border-right-width: 0;
- border-left: __sidebar_width__ solid __background_alt__;
+ border-left: @ini_sidebar_width solid @ini_background_alt;
}
+
.dokuwiki div.preview div.pad {
padding: 1.556em 0 2em;
}
-
/*____________ changes to _toc ____________*/
#dw__toc {
- margin: -1.556em -2em .5em 1.4em;
- width: __sidebar_width__;
- border-left: 1px solid __border__;
- background: __background__;
+ margin: -1.556em -2em .5em 1.4em;
+ width: @ini_sidebar_width;
+ border-left: 1px solid @ini_border;
+ background: @ini_background;
color: inherit;
}
+
[dir=rtl] #dw__toc {
margin: -1.556em 1.4em .5em -2em;
border-left-width: 0;
- border-right: 1px solid __border__;
+ border-right: 1px solid @ini_border;
}
.dokuwiki h3.toggle {
@@ -286,6 +296,7 @@
font-size: .875em;
letter-spacing: .1em;
}
+
#dokuwiki__aside h3.toggle {
display: none;
}
@@ -296,6 +307,7 @@
height: 5px;
margin: .4em 0 0;
}
+
.dokuwiki .toggle.closed strong {
background-position: 0 -5px;
}
@@ -304,59 +316,72 @@
display: none;
}
+#dw__toc {
+ > div {
+ font-size: 0.875em;
+ padding: .5em 1em 1em;
+ }
-#dw__toc > div {
- font-size: 0.875em;
- padding: .5em 1em 1em;
-}
-#dw__toc ul {
- padding: 0 0 0 1.2em;
+ ul {
+ padding: 0 0 0 1.2em;
+
+ li {
+ list-style-image: url(images/toc-bullet.png);
+ }
+ }
+
+ ul li.clear {
+ list-style: none;
+ }
+
+ ul li div.li {
+ padding: .2em 0;
+ }
}
+
[dir=rtl] #dw__toc ul {
padding: 0 1.5em 0 0;
}
-#dw__toc ul li {
- list-style-image: url(images/toc-bullet.png);
-}
-#dw__toc ul li.clear {
- list-style: none;
-}
-#dw__toc ul li div.li {
- padding: .2em 0;
-}
-
/*____________ changes to _imgdetail ____________*/
#dokuwiki__detail {
padding: 0;
-}
-#dokuwiki__detail img {
- float: none;
- margin-bottom: 1.4em;
-}
-#dokuwiki__detail div.img_detail {
- float: none;
-}
-#dokuwiki__detail div.img_detail dl {
- overflow: hidden;
-}
-#dokuwiki__detail div.img_detail dl dt {
- float: left;
- width: 9em;
- text-align: right;
- clear: left;
-}
-[dir=rtl] #dokuwiki__detail div.img_detail dl dt {
- float: right;
- text-align: left;
- clear: right;
-}
-#dokuwiki__detail div.img_detail dl dd {
- margin-left: 9.5em;
-}
-[dir=rtl] #dokuwiki__detail div.img_detail dl dd {
- margin-left: 0;
- margin-right: 9.5em;
-}
+ img {
+ float: none;
+ margin-bottom: 1.4em;
+ }
+
+ div.img_detail {
+ float: none;
+ }
+
+ div.img_detail dl {
+ overflow: hidden;
+ }
+
+ div.img_detail dl dt {
+ float: left;
+ width: 9em;
+ text-align: right;
+ clear: left;
+ }
+
+ div.img_detail dl dd {
+ margin-left: 9.5em;
+ }
+}
+
+[dir=rtl] #dokuwiki__detail div.img_detail {
+ dl dt {
+ float: right;
+ text-align: left;
+ clear: right;
+ }
+
+ dl dd {
+ margin-left: 0;
+ margin-right: 9.5em;
+ }
+} \ No newline at end of file
diff --git a/lib/tpl/dokuwiki/css/design.css b/lib/tpl/dokuwiki/css/design.css
deleted file mode 100644
index 457414839..000000000
--- a/lib/tpl/dokuwiki/css/design.css
+++ /dev/null
@@ -1,405 +0,0 @@
-/**
- * This file provides the main design styles for the
- * bits that surround the content.
- *
- * @author Anika Henke <anika@selfthinker.org>
- * @author Andreas Gohr <andi@splitbrain.org>
- * @author Clarence Lee <clarencedglee@gmail.com>
- */
-
-/* header
-********************************************************************/
-
-#dokuwiki__header {
- padding: 2em 0 1.5em;
-}
-
-#dokuwiki__header .headings,
-#dokuwiki__header .tools {
- margin-bottom: 1.5em;
- width: 49%;
-}
-#dokuwiki__header h1 img {
- float: left;
- margin-right: .5em;
-}
-[dir=rtl] #dokuwiki__header h1 img {
- float: right;
- margin-left: .5em;
- margin-right: 0;
-}
-#dokuwiki__header h1 span {
- display: block;
- padding-top: 10px;
-}
-#dokuwiki__header h1 {
- margin: 0;
- font-size: 1.5em;
- font-weight: normal;
-}
-#dokuwiki__header h1 a {
- text-decoration: none;
- color: __text__;
- background-color: inherit;
-}
-#dokuwiki__header h1 a:hover,
-#dokuwiki__header h1 a:active,
-#dokuwiki__header h1 a:focus {
-}
-#dokuwiki__header p.claim {
- margin-bottom: 0;
- font-size: 0.875em;
-}
-
-#dokuwiki__header .tools {
- margin-top: .2em;
-}
-
-
-/* tools
-********************************************************************/
-
-/* highlight selected tool */
-.mode_admin a.action.admin,
-.mode_login a.action.login,
-.mode_register a.action.register,
-.mode_profile a.action.profile,
-.mode_recent a.action.recent,
-.mode_index a.action.index,
-.mode_media a.action.media,
-.mode_revisions a.action.revs,
-.mode_backlink a.action.backlink,
-.mode_subscribe a.action.subscribe {
- font-weight: bold;
-}
-
-#dokuwiki__header .tools ul {
- padding-left: 0;
- margin-bottom: 0;
-}
-#dokuwiki__header .tools li {
- font-size: 0.875em;
- margin-left: 1em;
- list-style: none;
- display: inline;
-}
-[dir=rtl] #dokuwiki__header .tools li {
- margin-right: 1em;
- margin-left: 0;
-}
-#dokuwiki__header .tools form.search div.ajax_qsearch li {
- font-size: 1em;
- margin-left: 0;
- display: block;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-
-#dokuwiki__usertools a.action {
- padding-left: 20px;
- background: transparent url(images/usertools.png) no-repeat 0 0;
-}
-[dir=rtl] #dokuwiki__usertools a.action {
- padding-left: 0;
- padding-right: 20px;
-}
-[dir=rtl] #IE7 #dokuwiki__usertools a.action {
- display: inline-block;
-}
-
-
-#dokuwiki__header .mobileTools {
- display: none; /* hide mobile tools dropdown to only show in mobile view */
-}
-
-/*____________ user tools ____________*/
-
-#dokuwiki__usertools {
- position: absolute;
- top: .5em;
- right: .5em;
- text-align: right;
- width: 100%;
-}
-[dir=rtl] #dokuwiki__usertools {
- text-align: left;
- left: 40px;
- right: auto;
-}
-#dokuwiki__usertools ul {
- margin: 0 auto;
- padding: 0;
- max-width: __site_width__;
-}
-#dokuwiki__usertools ul li.user {
-}
-
-#dokuwiki__usertools a.action.admin {
- background-position: left 0;
-}
-[dir=rtl] #dokuwiki__usertools a.action.admin {
- background-position: right 0;
-}
-#dokuwiki__usertools a.action.profile {
- background-position: left -32px;
-}
-[dir=rtl] #dokuwiki__usertools a.action.profile {
- background-position: right -32px;
-}
-#dokuwiki__usertools a.action.register {
- background-position: left -64px;
-}
-[dir=rtl] #dokuwiki__usertools a.action.register {
- background-position: right -64px;
-}
-#dokuwiki__usertools a.action.login {
- background-position: left -96px;
-}
-[dir=rtl] #dokuwiki__usertools a.action.login {
- background-position: right -96px;
-}
-#dokuwiki__usertools a.action.logout {
- background-position: left -128px;
-}
-[dir=rtl] #dokuwiki__usertools a.action.logout {
- background-position: right -128px;
-}
-
-
-/*____________ site tools ____________*/
-
-#dokuwiki__sitetools {
- text-align: right;
-}
-[dir=rtl] #dokuwiki__sitetools {
- text-align: left;
-}
-
-#dokuwiki__sitetools form.search {
- display: block;
- font-size: 0.875em;
- position: relative;
-}
-#IE7 #dokuwiki__sitetools form.search {
- min-height: 1px;
- z-index: 21;
-}
-#dokuwiki__sitetools form.search input.edit {
- width: 18em;
- padding: .35em 22px .35em .1em;
-}
-[dir=rtl] #dokuwiki__sitetools form.search input.edit {
- padding: .35em .1em .35em 22px;
-}
-#dokuwiki__sitetools form.search input.button {
- background: transparent url(images/search.png) no-repeat 0 0;
- border-width: 0;
- width: 19px;
- height: 14px;
- text-indent: -99999px;
- margin-left: -20px;
- box-shadow: none;
- padding: 0;
-}
-[dir=rtl] #dokuwiki__sitetools form.search input.button {
- background-position: 5px 0;
- margin-left: 0;
- margin-right: -20px;
- position: relative;
-}
-
-#dokuwiki__sitetools ul {
- margin-top: 0.5em;
-}
-#dokuwiki__sitetools li {
-}
-
-/*____________ breadcrumbs ____________*/
-
-.dokuwiki div.breadcrumbs {
- border-top: 1px solid __border__;
- border-bottom: 1px solid __background__;
- margin-bottom: .5em;
- font-size: 0.875em;
- clear: both;
-}
-.dokuwiki div.breadcrumbs div {
- padding: .1em .35em;
-}
-
-.dokuwiki div.breadcrumbs div:only-child {
- border-top: 1px solid __background__;
- border-bottom: 1px solid __border__;
-}
-.dokuwiki div.breadcrumbs div:first-child {
- border-top: 1px solid __background__;
-}
-#IE7 .dokuwiki div.breadcrumbs div,
-#IE8 .dokuwiki div.breadcrumbs div {
- border-bottom: 1px solid __border__;
-}
-.dokuwiki div.breadcrumbs div:last-child {
- border-bottom: 1px solid __border__;
-}
-
-.dokuwiki div.breadcrumbs a {
- color: __link__;
- background-color: inherit;
-}
-.dokuwiki div.breadcrumbs .bcsep {
- font-size: 0.75em;
-}
-
-
-/* sidebar
-********************************************************************/
-
-#dokuwiki__aside {
-}
-#dokuwiki__aside > .pad {
- font-size: 0.875em;
- overflow: hidden;
- word-wrap: break-word;
-}
-
-/* make sidebar more condensed */
-
-#dokuwiki__aside h1 {
- font-size: 1.714em;
- margin-bottom: .292em;
-}
-#dokuwiki__aside h2 {
- margin-bottom: .333em;
-}
-#dokuwiki__aside h3 {
- margin-bottom: .444em;
-}
-#dokuwiki__aside h4 {
- margin-bottom: .5em;
-}
-#dokuwiki__aside h5 {
- margin-bottom: .5714em;
-}
-
-#dokuwiki__aside p,
-#dokuwiki__aside ul,
-#dokuwiki__aside ol,
-#dokuwiki__aside dl,
-#dokuwiki__aside pre,
-#dokuwiki__aside table,
-#dokuwiki__aside fieldset,
-#dokuwiki__aside hr,
-#dokuwiki__aside blockquote,
-#dokuwiki__aside address {
- margin-bottom: .7em;
-}
-
-#dokuwiki__aside ul,
-#dokuwiki__aside ol {
- padding-left: .5em;
-}
-[dir=rtl] #dokuwiki__aside ul,
-[dir=rtl] #dokuwiki__aside ol {
- padding-right: .5em;
-}
-#dokuwiki__aside li ul,
-#dokuwiki__aside li ol {
- margin-bottom: 0;
- padding: 0;
-}
-
-#dokuwiki__aside a:link,
-#dokuwiki__aside a:visited {
- color: __link__;
- background-color: inherit;
-}
-
-
-/* content
-********************************************************************/
-
-#dokuwiki__content {
-}
-
-.dokuwiki .pageId {
- position: absolute;
- top: -2.3em;
- right: -1em;
- overflow: hidden;
- padding: 1em 1em 0;
-}
-[dir=rtl] .dokuwiki .pageId {
- right: auto;
- left: -1em;
-}
-.dokuwiki .pageId span {
- font-size: 0.875em;
- border: solid __background_alt__;
- border-width: 1px 1px 0;
- background-color: __background__;
- color: __text_alt__;
- padding: .1em .35em;
- border-top-left-radius: 2px;
- border-top-right-radius: 2px;
- box-shadow: 0 0 .5em __text_alt__;
- display: block;
-}
-
-.dokuwiki div.page {
- background: __background__;
- color: inherit;
- border: 1px solid __background_alt__;
- box-shadow: 0 0 .5em __text_alt__;
- border-radius: 2px;
- padding: 1.556em 2em 2em;
- margin-bottom: .5em;
- overflow: hidden;
- word-wrap: break-word;
-}
-
-.dokuwiki .docInfo {
- font-size: 0.875em;
- text-align: right;
-}
-[dir=rtl] .dokuwiki .docInfo {
- text-align: left;
-}
-
-/* license note under edit window */
-.dokuwiki div.license {
- font-size: 93.75%;
-}
-
-
-/* footer
-********************************************************************/
-
-.dokuwiki .wrapper {
- margin-bottom: 1.4em;
-}
-
-#dokuwiki__footer {
- margin-bottom: 1em;
- text-align: center;
-}
-#dokuwiki__footer > .pad {
- font-size: 0.875em;
-}
-
-#dokuwiki__footer div.license {
- margin-bottom: 0.5em;
- font-size: 100%;
-}
-
-[dir=rtl] #dokuwiki__footer .license img {
- margin: 0 0 0 .5em;
-}
-
-#dokuwiki__footer div.buttons a img {
- opacity: 0.5;
-}
-#dokuwiki__footer div.buttons a:hover img,
-#dokuwiki__footer div.buttons a:active img,
-#dokuwiki__footer div.buttons a:focus img {
- opacity: 1;
-}
diff --git a/lib/tpl/dokuwiki/css/design.less b/lib/tpl/dokuwiki/css/design.less
new file mode 100644
index 000000000..42292de49
--- /dev/null
+++ b/lib/tpl/dokuwiki/css/design.less
@@ -0,0 +1,439 @@
+/**
+ * This file provides the main design styles for the
+ * bits that surround the content.
+ *
+ * @author Anika Henke <anika@selfthinker.org>
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Clarence Lee <clarencedglee@gmail.com>
+ */
+
+/* header
+********************************************************************/
+
+#dokuwiki__header {
+ padding: 2em 0 1.5em;
+
+ .headings,
+ .tools {
+ margin-bottom: 1.5em;
+ width: 49%;
+ }
+ .tools {
+ margin-top: .2em;
+ }
+
+ h1 {
+ margin: 0;
+ font-size: 1.5em;
+ font-weight: normal;
+
+ img {
+ float: left;
+ margin-right: .5em;
+ }
+
+ span {
+ display: block;
+ padding-top: 10px;
+ }
+
+ a {
+ text-decoration: none;
+ color: @ini_text;
+ background-color: inherit;
+ }
+ }
+
+ p.claim {
+ margin-bottom: 0;
+ font-size: 0.875em;
+ }
+}
+
+[dir=rtl] #dokuwiki__header h1 img {
+ float: right;
+ margin-left: .5em;
+ margin-right: 0;
+}
+
+/* tools
+********************************************************************/
+
+/* highlight selected tool */
+.mode_admin a.action.admin,
+.mode_login a.action.login,
+.mode_register a.action.register,
+.mode_profile a.action.profile,
+.mode_recent a.action.recent,
+.mode_index a.action.index,
+.mode_media a.action.media,
+.mode_revisions a.action.revs,
+.mode_backlink a.action.backlink,
+.mode_subscribe a.action.subscribe {
+ font-weight: bold;
+}
+
+#dokuwiki__header .tools {
+ ul {
+ padding-left: 0;
+ margin-bottom: 0;
+ }
+
+ li {
+ font-size: 0.875em;
+ margin-left: 1em;
+ list-style: none;
+ display: inline;
+ }
+
+ form.search div.ajax_qsearch li {
+ font-size: 1em;
+ margin-left: 0;
+ display: block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+}
+
+[dir=rtl] #dokuwiki__header .tools li {
+ margin-right: 1em;
+ margin-left: 0;
+}
+
+#dokuwiki__usertools a.action {
+ padding-left: 20px;
+ background: transparent url(images/usertools.png) no-repeat 0 0;
+}
+
+[dir=rtl] #dokuwiki__usertools a.action {
+ padding-left: 0;
+ padding-right: 20px;
+}
+
+[dir=rtl] #IE7 #dokuwiki__usertools a.action {
+ display: inline-block;
+}
+
+#dokuwiki__header .mobileTools {
+ display: none; /* hide mobile tools dropdown to only show in mobile view */
+}
+
+/*____________ user tools ____________*/
+
+#dokuwiki__usertools {
+ position: absolute;
+ top: .5em;
+ right: .5em;
+ text-align: right;
+ width: 100%;
+
+ ul {
+ margin: 0 auto;
+ padding: 0;
+ max-width: @ini_site_width;
+ }
+
+ a.action.admin {
+ background-position: left 0;
+ }
+
+ a.action.profile {
+ background-position: left -32px;
+ }
+
+ a.action.register {
+ background-position: left -64px;
+ }
+
+ a.action.login {
+ background-position: left -96px;
+ }
+
+ a.action.logout {
+ background-position: left -128px;
+ }
+}
+
+[dir=rtl] #dokuwiki__usertools {
+ text-align: left;
+ left: 40px;
+ right: auto;
+
+ a.action.admin {
+ background-position: right 0;
+ }
+
+ a.action.profile {
+ background-position: right -32px;
+ }
+
+ a.action.register {
+ background-position: right -64px;
+ }
+
+ a.action.login {
+ background-position: right -96px;
+ }
+
+ a.action.logout {
+ background-position: right -128px;
+ }
+}
+
+/*____________ site tools ____________*/
+
+#dokuwiki__sitetools {
+ text-align: right;
+
+ form.search {
+ display: block;
+ font-size: 0.875em;
+ position: relative;
+
+ input.edit {
+ width: 18em;
+ padding: .35em 22px .35em .1em;
+ }
+
+ input.button {
+ background: transparent url(images/search.png) no-repeat 0 0;
+ border-width: 0;
+ width: 19px;
+ height: 14px;
+ text-indent: -99999px;
+ margin-left: -20px;
+ box-shadow: none;
+ padding: 0;
+ }
+ }
+
+ ul {
+ margin-top: 0.5em;
+ }
+}
+
+[dir=rtl] #dokuwiki__sitetools {
+ text-align: left;
+
+ form.search {
+ input.edit {
+ padding: .35em .1em .35em 22px;
+ }
+
+ input.button {
+ background-position: 5px 0;
+ margin-left: 0;
+ margin-right: -20px;
+ position: relative;
+ }
+ }
+}
+
+#IE7 #dokuwiki__sitetools form.search {
+ min-height: 1px;
+ z-index: 21;
+}
+
+/*____________ breadcrumbs ____________*/
+
+.dokuwiki div.breadcrumbs {
+ border-top: 1px solid @ini_border;
+ border-bottom: 1px solid @ini_background;
+ margin-bottom: .5em;
+ font-size: 0.875em;
+ clear: both;
+
+ div {
+ padding: .1em .35em;
+ }
+
+ div:only-child {
+ border-top: 1px solid @ini_background;
+ border-bottom: 1px solid @ini_border;
+ }
+
+ div:first-child {
+ border-top: 1px solid @ini_background;
+ }
+
+ div:last-child {
+ border-bottom: 1px solid @ini_border;
+ }
+
+ a {
+ color: @ini_link;
+ background-color: inherit;
+ }
+
+ .bcsep {
+ font-size: 0.75em;
+ }
+}
+
+#IE7 .dokuwiki div.breadcrumbs div,
+#IE8 .dokuwiki div.breadcrumbs div {
+ border-bottom: 1px solid @ini_border;
+}
+
+/* sidebar
+********************************************************************/
+
+#dokuwiki__aside {
+
+ > .pad {
+ font-size: 0.875em;
+ overflow: hidden;
+ word-wrap: break-word;
+ }
+
+ /* make sidebar more condensed */
+
+ h1 {
+ font-size: 1.714em;
+ margin-bottom: .292em;
+ }
+
+ h2 {
+ margin-bottom: .333em;
+ }
+
+ h3 {
+ margin-bottom: .444em;
+ }
+
+ h4 {
+ margin-bottom: .5em;
+ }
+
+ h5 {
+ margin-bottom: .5714em;
+ }
+
+ p,
+ ul,
+ ol,
+ dl,
+ pre,
+ table,
+ fieldset,
+ hr,
+ blockquote,
+ address {
+ margin-bottom: .7em;
+ }
+
+ ul,
+ ol {
+ padding-left: .5em;
+ }
+
+ li ul,
+ li ol {
+ margin-bottom: 0;
+ padding: 0;
+ }
+
+ a:link,
+ a:visited {
+ color: @ini_link;
+ background-color: inherit;
+ }
+}
+
+[dir=rtl] #dokuwiki__aside ul,
+[dir=rtl] #dokuwiki__aside ol {
+ padding-right: .5em;
+}
+
+/* content
+********************************************************************/
+
+.dokuwiki .pageId {
+ position: absolute;
+ top: -2.3em;
+ right: -1em;
+ overflow: hidden;
+ padding: 1em 1em 0;
+
+ span {
+ font-size: 0.875em;
+ border: solid @ini_background_alt;
+ border-width: 1px 1px 0;
+ background-color: @ini_background;
+ color: @ini_text_alt;
+ padding: .1em .35em;
+ border-top-left-radius: 2px;
+ border-top-right-radius: 2px;
+ box-shadow: 0 0 .5em @ini_text_alt;
+ display: block;
+ }
+}
+
+.dokuwiki div.page {
+ background: @ini_background;
+ color: inherit;
+ border: 1px solid @ini_background_alt;
+ box-shadow: 0 0 .5em @ini_text_alt;
+ border-radius: 2px;
+ padding: 1.556em 2em 2em;
+ margin-bottom: .5em;
+ overflow: hidden;
+ word-wrap: break-word;
+}
+
+.dokuwiki .docInfo {
+ font-size: 0.875em;
+ text-align: right;
+}
+
+/* license note under edit window */
+.dokuwiki div.license {
+ font-size: 93.75%;
+}
+
+[dir=rtl] .dokuwiki .docInfo {
+ text-align: left;
+}
+
+[dir=rtl] .dokuwiki .pageId {
+ right: auto;
+ left: -1em;
+}
+
+/* footer
+********************************************************************/
+
+.dokuwiki .wrapper {
+ margin-bottom: 1.4em;
+}
+
+#dokuwiki__footer {
+ margin-bottom: 1em;
+ text-align: center;
+
+ > .pad {
+ font-size: 0.875em;
+ }
+
+ div.license {
+ margin-bottom: 0.5em;
+ font-size: 100%;
+ }
+
+ div.buttons a {
+ img {
+ opacity: 0.5;
+ }
+
+ &:hover img,
+ &:active img,
+ &:focus img {
+ opacity: 1;
+ }
+ }
+
+}
+
+[dir=rtl] #dokuwiki__footer .license img {
+ margin: 0 0 0 .5em;
+}
diff --git a/lib/tpl/dokuwiki/css/includes.css b/lib/tpl/dokuwiki/css/includes.css
deleted file mode 100644
index bc189962f..000000000
--- a/lib/tpl/dokuwiki/css/includes.css
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * This file provides styles for included seperate html files
- * (added through "include hooks").
- */
diff --git a/lib/tpl/dokuwiki/css/mixins.less b/lib/tpl/dokuwiki/css/mixins.less
new file mode 100644
index 000000000..a88767e97
--- /dev/null
+++ b/lib/tpl/dokuwiki/css/mixins.less
@@ -0,0 +1,10 @@
+/**
+ * linear gradient x-browser support
+ */
+.linear-gradient(@declaration: 0) {
+ background: -moz-linear-gradient( @declaration);
+ background: -webkit-linear-gradient(@declaration);
+ background: -o-linear-gradient( @declaration);
+ background: -ms-linear-gradient( @declaration);
+ background: linear-gradient( @declaration);
+} \ No newline at end of file
diff --git a/lib/tpl/dokuwiki/css/mobile.css b/lib/tpl/dokuwiki/css/mobile.less
index 71f80599d..289f5afa3 100644
--- a/lib/tpl/dokuwiki/css/mobile.css
+++ b/lib/tpl/dokuwiki/css/mobile.less
@@ -13,7 +13,7 @@
/* for screen widths in the tablet range
********************************************************************/
-@media only screen and (max-width: __tablet_width__) {
+@media only screen and (max-width: @ini_tablet_width) {
#screen__mode {
z-index: 1; /* for detecting media queries in JavaScript (see script.js) */
@@ -29,10 +29,10 @@
[dir=rtl] #dokuwiki__aside > .pad {
margin: 0 0 .5em;
/* style like .page */
- background: __background__;
+ background: @ini_background;
color: inherit;
border: 1px solid #eee;
- box-shadow: 0 0 .5em __text_alt__;
+ box-shadow: 0 0 .5em @ini_text_alt;
border-radius: 2px;
padding: 1em;
margin-bottom: .5em;
@@ -40,22 +40,24 @@
#dokuwiki__aside h3.toggle {
font-size: 1em;
-}
-#dokuwiki__aside h3.toggle.closed {
- margin-bottom: 0;
- padding-bottom: 0;
-}
-#dokuwiki__aside h3.toggle.open {
- border-bottom: 1px solid __border__;
+
+ &.closed {
+ margin-bottom: 0;
+ padding-bottom: 0;
+ }
+ &.open {
+ border-bottom: 1px solid @ini_border;
+ }
}
.showSidebar #dokuwiki__content {
float: none;
margin-left: 0;
width: 100%;
-}
-.showSidebar #dokuwiki__content > .pad {
- margin-left: 0;
+
+ > .pad {
+ margin-left: 0;
+ }
}
[dir=rtl] .showSidebar #dokuwiki__content,
@@ -69,7 +71,7 @@
margin: 0 0 1em 0;
width: auto;
border-left-width: 0;
- border-bottom: 1px solid __border__;
+ border-bottom: 1px solid @ini_border;
}
[dir=rtl] #dw__toc {
float: none;
@@ -119,7 +121,7 @@
/* for screen widths in the smartphone range
********************************************************************/
-@media only screen and (max-width: __phone_width__) {
+@media only screen and (max-width: @ini_phone_width) {
#screen__mode {
z-index: 2; /* for detecting media queries in JavaScript (see script.js) */
@@ -133,9 +135,10 @@ body {
#dokuwiki__site {
max-width: 100%;
-}
-#dokuwiki__site > .site {
- padding: 0 .5em;
+
+ > .site {
+ padding: 0 .5em;
+ }
}
#dokuwiki__header {
padding: .5em 0;
@@ -154,19 +157,21 @@ body {
list-style: none;
padding-left: 0;
margin: 0;
+
+ li {
+ margin-left: .35em;
+ display: inline;
+ }
}
[dir=rtl] #dokuwiki__header ul.a11y.skip {
left: auto !important;
right: 0 !important;
float: left;
padding-right: 0;
-}
-#dokuwiki__header ul.a11y.skip li {
- margin-left: .35em;
- display: inline;
-}
-[dir=rtl] #dokuwiki__header ul.a11y.skip li {
- margin: 0 .35em 0 0;
+
+ li {
+ margin: 0 .35em 0 0;
+ }
}
#dokuwiki__header .headings,
@@ -264,13 +269,14 @@ body {
.dokuwiki label.block {
text-align: left;
+
+ span {
+ display: block;
+ }
}
[dir=rtl] .dokuwiki label.block {
text-align: right;
}
-.dokuwiki label.block span {
- display: block;
-}
/* _edit */
.dokuwiki div.section_highlight {
diff --git a/lib/tpl/dokuwiki/css/pagetools.css b/lib/tpl/dokuwiki/css/pagetools.css
deleted file mode 100644
index 98e4ff1fc..000000000
--- a/lib/tpl/dokuwiki/css/pagetools.css
+++ /dev/null
@@ -1,424 +0,0 @@
-/**
- * This file provides the styles for the page tools
- * (fly out navigation beside the page to edit, etc).
- *
- * @author Anika Henke <anika@selfthinker.org>
- * @author Andreas Gohr <andi@splitbrain.org>
- */
-
-#dokuwiki__site > .site {
- /* give space to the right so the tools won't disappear on smaller screens */
- /* it's 40px because the 30px wide icons will have 5px more spacing to the left and right */
- padding-right: 40px;
- /* give the same space to the left to balance it out */
- padding-left: 40px;
-}
-.dokuwiki div.page {
- height: 190px;
- min-height: 190px; /* 30 (= height of icons) x 6 (= maximum number of possible tools) + 2x5 */
- height: auto;
-}
-#dokuwiki__usertools {
- /* move the tools just outside of the site */
- right: 40px;
-}
-[dir=rtl] #dokuwiki__usertools {
- right: auto;
- left: 40px;
-}
-
-
-#dokuwiki__pagetools {
- position: absolute;
- right: -40px;
- /* on same vertical level as first headline, because .page has 2em padding */
- top: 2em;
- width: 40px;
-}
-[dir=rtl] #dokuwiki__pagetools {
- right: auto;
- left: -40px;
-}
-
-#dokuwiki__pagetools div.tools {
- position: fixed;
- width: 40px;
-}
-
-#dokuwiki__pagetools ul {
- position: absolute;
- right: 0;
- text-align: right;
- margin: 0;
- padding: 0;
- /* add transparent border to prevent jumping when proper border is added on hover */
- border: 1px solid transparent;
- z-index: 10;
-}
-[dir=rtl] #dokuwiki__pagetools ul {
- right: auto;
- left: 0;
- text-align: left;
-}
-
-#dokuwiki__pagetools ul li {
- padding: 0;
- margin: 0;
- list-style: none;
- font-size: 0.875em;
-}
-
-#dokuwiki__pagetools ul li a {
- display: block;
- min-height: 20px; /* 30 - 2x5 */
- line-height: 20px;
- padding: 0;
- background-position: right 0;
- background-repeat: no-repeat;
- /* add transparent border to prevent jumping when proper border is added on focus */
- border: 1px solid transparent;
- white-space: nowrap;
- width: 30px;
- height: 30px;
- overflow: hidden;
- margin-left: auto; /* align right if the ul is larger because one item is focused */
-}
-
-#dokuwiki__pagetools ul li a:before {
- content: url(images/pagetools-sprite.png?v=2);
- display: inline-block;
- font-size: 0;
- line-height: 0;
-}
-
-[dir=rtl] #dokuwiki__pagetools ul li a {
- background-position: left 0;
- margin-right: auto;
- margin-left: 0;
-}
-
-/* show all tools on hover and individual tools on focus */
-#dokuwiki__pagetools:hover ul,
-#dokuwiki__pagetools ul li a:focus,
-#dokuwiki__pagetools ul li a:active {
- background-color: __background__;
- border-color: __border__;
- border-radius: 2px;
- box-shadow: 2px 2px 2px __text_alt__;
-}
-
-#dokuwiki__pagetools:hover ul li a,
-#dokuwiki__pagetools ul li a:focus,
-#dokuwiki__pagetools ul li a:active {
- width: auto;
- height: auto;
- overflow: visible;
- padding: 5px 40px 5px 5px;
- background-image: url(images/pagetools-sprite.png);
-}
-
-#dokuwiki__pagetools:hover ul li a:before,
-#dokuwiki__pagetools ul li a:focus:before {
- content: none;
-}
-
-[dir=rtl] #dokuwiki__pagetools:hover ul,
-[dir=rtl] #dokuwiki__pagetools ul li a:focus {
- box-shadow: -2px 2px 2px __text_alt__;
-}
-
-[dir=rtl] #dokuwiki__pagetools:hover li a,
-[dir=rtl] #dokuwiki__pagetools ul li a:focus,
-[dir=rtl] #dokuwiki__pagetools ul li a:active {
- padding: 5px 5px 5px 40px;
-}
-
-/* IE7 fixes, doesn't work without images */
-
-#IE7 #dokuwiki__pagetools ul li a {
- background-image: url(images/pagetools-sprite.png);
-}
-
-#IE7 #dokuwiki__pagetools:hover ul li a span,
-#IE7 #dokuwiki__pagetools ul li a:focus span,
-#IE7 #dokuwiki__pagetools ul li a:active span {
- clip: auto;
- display: inline;
- position: static;
-}
-
-#IE7 #dokuwiki__pagetools ul li a span {
- clip: rect(0 0 0 0);
- position: absolute;
-}
-
-#dokuwiki__pagetools ul li a:hover,
-#dokuwiki__pagetools ul li a:active,
-#dokuwiki__pagetools ul li a:focus {
- text-decoration: none;
-}
-#dokuwiki__pagetools ul li a:hover {
- background-color: __background_alt__;
-}
-
-/*____________ all available icons in sprite ____________*/
-
-#dokuwiki__pagetools ul li a.edit:before {
- margin-top: -90px;
-}
-#dokuwiki__pagetools ul li a.edit {
- background-position: right -90px;
-}
-#dokuwiki__pagetools ul li a.edit:hover,
-#dokuwiki__pagetools ul li a.edit:active,
-#dokuwiki__pagetools ul li a.edit:focus {
- background-position: right -135px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.edit {
- background-position: left -90px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.edit:hover,
-[dir=rtl] #dokuwiki__pagetools ul li a.edit:active,
-[dir=rtl] #dokuwiki__pagetools ul li a.edit:focus {
- background-position: left -135px;
-}
-
-#dokuwiki__pagetools ul li a.create:before {
- margin-top: -180px;
-}
-#dokuwiki__pagetools ul li a.create {
- background-position: right -180px;
-}
-#dokuwiki__pagetools ul li a.create:hover,
-#dokuwiki__pagetools ul li a.create:active,
-#dokuwiki__pagetools ul li a.create:focus {
- background-position: right -225px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.create {
- background-position: left -180px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.create:hover,
-[dir=rtl] #dokuwiki__pagetools ul li a.create:active,
-[dir=rtl] #dokuwiki__pagetools ul li a.create:focus {
- background-position: left -225px;
-}
-
-#dokuwiki__pagetools ul li a.show {
- background-position: right -360px;
-}
-#dokuwiki__pagetools ul li a.show:before {
- margin-top: -360px;
-}
-#dokuwiki__pagetools ul li a.show:hover,
-#dokuwiki__pagetools ul li a.show:active,
-#dokuwiki__pagetools ul li a.show:focus {
- background-position: right -405px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.show {
- background-position: left -360px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.show:hover,
-[dir=rtl] #dokuwiki__pagetools ul li a.show:active,
-[dir=rtl] #dokuwiki__pagetools ul li a.show:focus {
- background-position: left -405px;
-}
-
-#dokuwiki__pagetools ul li a.source {
- background-position: right -450px;
-}
-#dokuwiki__pagetools ul li a.source:before {
- margin-top: -450px;
-}
-#dokuwiki__pagetools ul li a.source:hover,
-#dokuwiki__pagetools ul li a.source:active,
-#dokuwiki__pagetools ul li a.source:focus {
- background-position: right -495px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.source {
- background-position: left -450px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.source:hover,
-[dir=rtl] #dokuwiki__pagetools ul li a.source:active,
-[dir=rtl] #dokuwiki__pagetools ul li a.source:focus {
- background-position: left -495px;
-}
-
-#dokuwiki__pagetools ul li a.draft {
- background-position: right -270px;
-}
-#dokuwiki__pagetools ul li a.draft:before {
- margin-top: -270px;
-}
-#dokuwiki__pagetools ul li a.draft:hover,
-#dokuwiki__pagetools ul li a.draft:active,
-#dokuwiki__pagetools ul li a.draft:focus {
- background-position: right -315px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.draft {
- background-position: left -270px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.draft:hover,
-[dir=rtl] #dokuwiki__pagetools ul li a.draft:active,
-[dir=rtl] #dokuwiki__pagetools ul li a.draft:focus {
- background-position: left -315px;
-}
-
-#dokuwiki__pagetools ul li a.revs {
- background-position: right -630px;
-}
-#dokuwiki__pagetools ul li a.revs:before {
- margin-top: -630px;
-}
-#dokuwiki__pagetools ul li a.revs:hover,
-#dokuwiki__pagetools ul li a.revs:active,
-#dokuwiki__pagetools ul li a.revs:focus,
-.mode_revisions #dokuwiki__pagetools ul li a.revs {
- background-position: right -675px;
-}
-.mode_revisions #dokuwiki__pagetools ul li a.revs:before {
- margin-top: -675px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.revs {
- background-position: left -630px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.revs:hover,
-[dir=rtl] #dokuwiki__pagetools ul li a.revs:active,
-[dir=rtl] #dokuwiki__pagetools ul li a.revs:focus,
-[dir=rtl] .mode_revisions #dokuwiki__pagetools ul li a.revs {
- background-position: left -675px;
-}
-
-#dokuwiki__pagetools ul li a.backlink {
- background-position: right -720px;
-}
-#dokuwiki__pagetools ul li a.backlink:before {
- margin-top: -720px;
-}
-#dokuwiki__pagetools ul li a.backlink:hover,
-#dokuwiki__pagetools ul li a.backlink:active,
-#dokuwiki__pagetools ul li a.backlink:focus,
-.mode_backlink #dokuwiki__pagetools ul li a.backlink {
- background-position: right -765px;
-}
-.mode_backlink #dokuwiki__pagetools ul li a.backlink:before {
- margin-top: -765px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.backlink {
- background-position: left -720px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.backlink:hover,
-[dir=rtl] #dokuwiki__pagetools ul li a.backlink:active,
-[dir=rtl] #dokuwiki__pagetools ul li a.backlink:focus,
-[dir=rtl] .mode_backlink #dokuwiki__pagetools ul li a.backlink {
- background-position: left -765px;
-}
-
-#dokuwiki__pagetools ul li a.top {
- background-position: right -900px;
-}
-#dokuwiki__pagetools ul li a.top:before{
- margin-top: -900px;
-}
-#dokuwiki__pagetools ul li a.top:hover,
-#dokuwiki__pagetools ul li a.top:active,
-#dokuwiki__pagetools ul li a.top:focus {
- background-position: right -945px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.top {
- background-position: left -900px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.top:hover,
-[dir=rtl] #dokuwiki__pagetools ul li a.top:active,
-[dir=rtl] #dokuwiki__pagetools ul li a.top:focus {
- background-position: left -945px;
-}
-
-#dokuwiki__pagetools ul li a.revert {
- background-position: right -540px;
-}
-#dokuwiki__pagetools ul li a.revert:before {
- margin-top: -540px;
-}
-#dokuwiki__pagetools ul li a.revert:hover,
-#dokuwiki__pagetools ul li a.revert:active,
-#dokuwiki__pagetools ul li a.revert:focus,
-.mode_revert #dokuwiki__pagetools ul li a.revert {
- background-position: right -585px;
-}
-.mode_revert #dokuwiki__pagetools ul li a.revert:before {
- margin-top: -540px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.revert {
- background-position: left -540px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.revert:hover,
-[dir=rtl] #dokuwiki__pagetools ul li a.revert:active,
-[dir=rtl] #dokuwiki__pagetools ul li a.revert:focus,
-[dir=rtl] .mode_revert #dokuwiki__pagetools ul li a.revert {
- background-position: left -585px;
-}
-
-#dokuwiki__pagetools ul li a.subscribe {
- background-position: right -810px;
-}
-#dokuwiki__pagetools ul li a.subscribe:before {
- margin-top: -810px;
-}
-#dokuwiki__pagetools ul li a.subscribe:hover,
-#dokuwiki__pagetools ul li a.subscribe:active,
-#dokuwiki__pagetools ul li a.subscribe:focus,
-.mode_subscribe #dokuwiki__pagetools ul li a.subscribe {
- background-position: right -855px;
-}
-.mode_subscribe #dokuwiki__pagetools ul li a.subscribe:before {
- margin-top: -855px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.subscribe {
- background-position: left -810px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.subscribe:hover,
-[dir=rtl] #dokuwiki__pagetools ul li a.subscribe:active,
-[dir=rtl] #dokuwiki__pagetools ul li a.subscribe:focus,
-[dir=rtl] .mode_subscribe #dokuwiki__pagetools ul li a.subscribe {
- background-position: left -855px;
-}
-
-#dokuwiki__pagetools ul li a.mediaManager {
- background-position: right -990px;
-}
-#dokuwiki__pagetools ul li a.mediaManager:before {
- margin-top: -990px;
-}
-#dokuwiki__pagetools ul li a.mediaManager:hover,
-#dokuwiki__pagetools ul li a.mediaManager:active,
-#dokuwiki__pagetools ul li a.mediaManager:focus {
- background-position: right -1035px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.mediaManager {
- background-position: left -990px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.mediaManager:hover,
-[dir=rtl] #dokuwiki__pagetools ul li a.mediaManager:active,
-[dir=rtl] #dokuwiki__pagetools ul li a.mediaManager:focus {
- background-position: left -1035px;
-}
-
-#dokuwiki__pagetools ul li a.back {
- background-position: right -1080px;
-}
-#dokuwiki__pagetools ul li a.back:before {
- margin-top: -1080px;
-}
-#dokuwiki__pagetools ul li a.back:hover,
-#dokuwiki__pagetools ul li a.back:active,
-#dokuwiki__pagetools ul li a.back:focus {
- background-position: right -1125px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.back {
- background-position: left -1080px;
-}
-[dir=rtl] #dokuwiki__pagetools ul li a.back:hover,
-[dir=rtl] #dokuwiki__pagetools ul li a.back:active,
-[dir=rtl] #dokuwiki__pagetools ul li a.back:focus {
- background-position: left -1125px;
-}
diff --git a/lib/tpl/dokuwiki/css/pagetools.less b/lib/tpl/dokuwiki/css/pagetools.less
new file mode 100644
index 000000000..ecb3038c3
--- /dev/null
+++ b/lib/tpl/dokuwiki/css/pagetools.less
@@ -0,0 +1,233 @@
+/**
+ * This file provides the styles for the page tools
+ * (fly out navigation beside the page to edit, etc).
+ *
+ * @author Anika Henke <anika@selfthinker.org>
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+
+#dokuwiki__site > .site {
+ /* give space to the right so the tools won't disappear on smaller screens */
+ /* it's 40px because the 30px wide icons will have 5px more spacing to the left and right */
+ padding-right: 40px;
+ /* give the same space to the left to balance it out */
+ padding-left: 40px;
+}
+.dokuwiki div.page {
+ height: 190px;
+ min-height: 190px; /* 30 (= height of icons) x 6 (= maximum number of possible tools) + 2x5 */
+ height: auto;
+}
+#dokuwiki__usertools {
+ /* move the tools just outside of the site */
+ right: 40px;
+}
+[dir=rtl] #dokuwiki__usertools {
+ right: auto;
+ left: 40px;
+}
+
+
+#dokuwiki__pagetools {
+ position: absolute;
+ right: -40px;
+ /* on same vertical level as first headline, because .page has 2em padding */
+ top: 2em;
+ width: 40px;
+}
+[dir=rtl] #dokuwiki__pagetools {
+ right: auto;
+ left: -40px;
+}
+
+#dokuwiki__pagetools div.tools {
+ position: fixed;
+ width: 40px;
+}
+
+#dokuwiki__pagetools ul {
+ position: absolute;
+ right: 0;
+ text-align: right;
+ margin: 0;
+ padding: 0;
+ /* add transparent border to prevent jumping when proper border is added on hover */
+ border: 1px solid transparent;
+ z-index: 10;
+}
+[dir=rtl] #dokuwiki__pagetools ul {
+ right: auto;
+ left: 0;
+ text-align: left;
+}
+
+#dokuwiki__pagetools ul li {
+ padding: 0;
+ margin: 0;
+ list-style: none;
+ font-size: 0.875em;
+}
+
+#dokuwiki__pagetools ul li a {
+ display: block;
+ min-height: 20px; /* 30 - 2x5 */
+ line-height: 20px;
+ padding: 0;
+ background-position: right 0;
+ background-repeat: no-repeat;
+ /* add transparent border to prevent jumping when proper border is added on focus */
+ border: 1px solid transparent;
+ white-space: nowrap;
+ width: 30px;
+ height: 30px;
+ overflow: hidden;
+ margin-left: auto; /* align right if the ul is larger because one item is focused */
+}
+
+#dokuwiki__pagetools ul li a:before {
+ content: url(images/pagetools-sprite.png?v=2);
+ display: inline-block;
+ font-size: 0;
+ line-height: 0;
+}
+
+[dir=rtl] #dokuwiki__pagetools ul li a {
+ background-position: left 0;
+ margin-right: auto;
+ margin-left: 0;
+}
+
+/* show all tools on hover and individual tools on focus */
+#dokuwiki__pagetools:hover ul,
+#dokuwiki__pagetools ul li a:focus,
+#dokuwiki__pagetools ul li a:active {
+ background-color: @ini_background;
+ border-color: @ini_border;
+ border-radius: 2px;
+ box-shadow: 2px 2px 2px @ini_text_alt;
+}
+
+#dokuwiki__pagetools:hover ul li a,
+#dokuwiki__pagetools ul li a:focus,
+#dokuwiki__pagetools ul li a:active {
+ width: auto;
+ height: auto;
+ overflow: visible;
+ padding: 5px 40px 5px 5px;
+ background-image: url(images/pagetools-sprite.png?v=2);
+}
+
+#dokuwiki__pagetools:hover ul li a:before,
+#dokuwiki__pagetools ul li a:focus:before {
+ content: none;
+}
+
+[dir=rtl] #dokuwiki__pagetools:hover ul,
+[dir=rtl] #dokuwiki__pagetools ul li a:focus {
+ box-shadow: -2px 2px 2px @ini_text_alt;
+}
+
+[dir=rtl] #dokuwiki__pagetools:hover li a,
+[dir=rtl] #dokuwiki__pagetools ul li a:focus,
+[dir=rtl] #dokuwiki__pagetools ul li a:active {
+ padding: 5px 5px 5px 40px;
+}
+
+/* IE7 fixes, doesn't work without images */
+
+#IE7 #dokuwiki__pagetools ul li a {
+ background-image: url(images/pagetools-sprite.png?v=2);
+}
+
+#IE7 #dokuwiki__pagetools:hover ul li a span,
+#IE7 #dokuwiki__pagetools ul li a:focus span,
+#IE7 #dokuwiki__pagetools ul li a:active span {
+ clip: auto;
+ display: inline;
+ position: static;
+}
+
+#IE7 #dokuwiki__pagetools ul li a span {
+ clip: rect(0 0 0 0);
+ position: absolute;
+}
+
+#dokuwiki__pagetools ul li a:hover,
+#dokuwiki__pagetools ul li a:active,
+#dokuwiki__pagetools ul li a:focus {
+ text-decoration: none;
+}
+#dokuwiki__pagetools ul li a:hover {
+ background-color: @ini_background_alt;
+}
+
+/*____________ all available icons in sprite ____________*/
+
+@pagetools_icon_space: -90px;
+
+/**
+ * page tools without highlighting
+ *
+ * @param string @action The action class
+ * @param int @position Position in the page tools sprite
+ */
+.pagetools-item(@action, @position) {
+ @position-active: (@position+0.5);
+
+ #dokuwiki__pagetools ul li a.@{action} {
+ background-position: right @pagetools_icon_space * @position;
+
+ &:before {
+ margin-top: @pagetools_icon_space * @position;
+ }
+ &:hover,
+ &:active,
+ &:focus {
+ background-position: right @pagetools_icon_space * @position-active;
+ }
+ }
+ [dir=rtl] #dokuwiki__pagetools ul li a.@{action} {
+ background-position: left @pagetools_icon_space * @position;
+
+ &:hover,
+ &:active,
+ &:focus {
+ background-position: left @pagetools_icon_space * @position-active;
+ }
+ }
+}
+
+/**
+ * page tools with highlighting
+ *
+ * @param string @action The action class
+ * @param int @position Position in the page tools sprite
+ * @param string @mode The mode in which this tool should be highlighted
+ */
+.pagetools-item(@action, @position, @mode) {
+ .pagetools-item(@action, @position);
+ @position-active: (@position+0.5);
+
+ .mode_@{mode} #dokuwiki__pagetools ul li a.@{action} {
+ background-position: right @pagetools_icon_space * @position-active;
+ &:before {
+ margin-top: @pagetools_icon_space * @position-active;
+ }
+ }
+ [dir=rtl] .mode_@{mode} #dokuwiki__pagetools ul li a.@{action} {
+ background-position: left @pagetools_icon_space * @position-active;
+ }
+}
+
+.pagetools-item(edit, 1);
+.pagetools-item(create, 2);
+.pagetools-item(show, 4);
+.pagetools-item(source, 5);
+.pagetools-item(draft, 3);
+.pagetools-item(revs, 7, revisions);
+.pagetools-item(backlink, 8, backlink);
+.pagetools-item(top, 10);
+.pagetools-item(revert, 6, revert);
+.pagetools-item(subscribe, 9, subscribe);
+.pagetools-item(mediaManager, 11);
+.pagetools-item(back, 12);
diff --git a/lib/tpl/dokuwiki/css/structure.css b/lib/tpl/dokuwiki/css/structure.css
deleted file mode 100644
index 00642e90b..000000000
--- a/lib/tpl/dokuwiki/css/structure.css
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * This file provides styles for the general layout structure.
- *
- * @author Anika Henke <anika@selfthinker.org>
- */
-
-body {
- margin: 0 auto;
-}
-#dokuwiki__site {
- margin: 0 auto;
- max-width: __site_width__;
-}
-#dokuwiki__site > .site {
- padding: 0 .5em;
-}
-
-#dokuwiki__header {
- width: 100%;
-}
-#dokuwiki__header > .pad {
-}
- #dokuwiki__header .headings {
- float: left;
- }
- [dir=rtl] #dokuwiki__header .headings {
- float: right;
- text-align: right;
- }
- #dokuwiki__header .tools {
- float: right;
- text-align: right;
- }
- [dir=rtl] #dokuwiki__header .tools {
- float: left;
- text-align: left;
- }
-
-#dokuwiki__site .wrapper {
- position: relative;
-}
-
- #dokuwiki__aside {
- width: __sidebar_width__;
- float: left;
- position: relative;
- display: block;
- }
- [dir=rtl] #dokuwiki__aside {
- float: right;
- }
- #dokuwiki__aside > .pad {
- margin: 0 1.5em 0 0;
- }
- [dir=rtl] #dokuwiki__aside > .pad {
- margin: 0 0 0 1.5em;
- }
-
- .showSidebar #dokuwiki__content {
- float: right;
- margin-left: -__sidebar_width__;
- width: 100%;
- }
- [dir=rtl] .showSidebar #dokuwiki__content {
- float: left;
- margin-left: 0;
- margin-right: -__sidebar_width__;
- }
- .showSidebar #dokuwiki__content > .pad {
- margin-left: __sidebar_width__;
- }
- [dir=rtl] .showSidebar #dokuwiki__content > .pad {
- margin-left: 0;
- margin-right: __sidebar_width__;
- }
-
-#dokuwiki__footer {
- clear: both;
-}
-#dokuwiki__footer > .pad {
-}
diff --git a/lib/tpl/dokuwiki/css/structure.less b/lib/tpl/dokuwiki/css/structure.less
new file mode 100644
index 000000000..3ea2f83eb
--- /dev/null
+++ b/lib/tpl/dokuwiki/css/structure.less
@@ -0,0 +1,89 @@
+/**
+ * This file provides styles for the general layout structure.
+ *
+ * @author Anika Henke <anika@selfthinker.org>
+ */
+body {
+ margin: 0 auto;
+}
+
+#dokuwiki__site {
+ margin: 0 auto;
+ max-width: @ini_site_width;
+}
+
+#dokuwiki__site > .site {
+ padding: 0 .5em;
+}
+
+#dokuwiki__header {
+ width: 100%;
+
+ .headings {
+ float: left;
+ }
+
+ .tools {
+ float: right;
+ text-align: right;
+ }
+}
+
+[dir=rtl] #dokuwiki__header {
+ .headings {
+ float: right;
+ text-align: right;
+ }
+
+ .tools {
+ float: left;
+ text-align: left;
+ }
+}
+
+#dokuwiki__site .wrapper {
+ position: relative;
+}
+
+#dokuwiki__aside {
+ width: @ini_sidebar_width;
+ float: left;
+ position: relative;
+ display: block;
+
+ > .pad {
+ margin: 0 1.5em 0 0;
+ }
+}
+
+[dir=rtl] #dokuwiki__aside {
+ float: right;
+ > .pad {
+ margin: 0 0 0 1.5em;
+ }
+}
+
+.showSidebar #dokuwiki__content {
+ float: right;
+ margin-left: (-1 * @ini_sidebar_width);
+ width: 100%;
+
+ > .pad {
+ margin-left: @ini_sidebar_width;
+ }
+}
+
+[dir=rtl] .showSidebar #dokuwiki__content {
+ float: left;
+ margin-left: 0;
+ margin-right: (-1 * @ini_sidebar_width);
+
+ > .pad {
+ margin-left: 0;
+ margin-right: @ini_sidebar_width;
+ }
+}
+
+#dokuwiki__footer {
+ clear: both;
+}
diff --git a/lib/tpl/dokuwiki/style.ini b/lib/tpl/dokuwiki/style.ini
index 77bb98236..897b6e6da 100644
--- a/lib/tpl/dokuwiki/style.ini
+++ b/lib/tpl/dokuwiki/style.ini
@@ -9,10 +9,15 @@
; Define the stylesheets your template uses here. The second value
; defines for which output media the style should be loaded. Currently
; print, screen and all are supported.
+; You can reference CSS and LESS files here. Files referenced here will
+; be checked for updates when considering a cache rebuild while files
+; included through LESS' @import statements are not
[stylesheets]
-css/basic.css = screen
+css/mixins.less = screen
+
+css/basic.less = screen
css/_imgdetail.css = screen
css/_media_popup.css = screen
css/_media_fullscreen.css = screen
@@ -28,19 +33,20 @@ css/_edit.css = screen
css/_modal.css = screen
css/_forms.css = screen
css/_admin.css = screen
-css/structure.css = screen
-css/design.css = screen
-css/pagetools.css = screen
-css/content.css = screen
-css/includes.css = screen
+css/structure.less = screen
+css/design.less = screen
+css/pagetools.less = screen
+css/content.less = screen
-css/mobile.css = all
+css/mobile.less = all
css/print.css = print
; This section is used to configure some placeholder values used in
; the stylesheets. Changing this file is the simplest method to
; give your wiki a new look.
+; Placeholders defined here will also be made available as LESS variables
+; (with surrounding underscores removed, and the prefix @ini_ added)
[replacements]
@@ -48,32 +54,32 @@ css/print.css = print
;------ guaranteed dokuwiki color placeholders that every plugin can use
; main text and background colors
-__text__ = "#333"
-__background__ = "#fff"
+__text__ = "#333" ; @ini_text
+__background__ = "#fff" ; @ini_background
; alternative text and background colors
-__text_alt__ = "#999"
-__background_alt__ = "#eee"
+__text_alt__ = "#999" ; @ini_text_alt
+__background_alt__ = "#eee" ; @ini_background_alt
; neutral text and background colors
-__text_neu__ = "#666"
-__background_neu__ = "#ddd"
+__text_neu__ = "#666" ; @ini_text_neu
+__background_neu__ = "#ddd" ; @ini_background_neu
; border color
-__border__ = "#ccc"
+__border__ = "#ccc" ; @ini_border
; highlighted text (e.g. search snippets)
-__highlight__ = "#ff9"
+__highlight__ = "#ff9" ; @ini_highlight
;--------------------------------------------------------------------------
-__background_site__ = "#fbfaf9"
+__background_site__ = "#fbfaf9" ; @ini_background_site
; these are used for links
-__link__ = "#2b73b7"
-__existing__ = "#080"
-__missing__ = "#d30"
+__link__ = "#2b73b7" ; @ini_link
+__existing__ = "#080" ; @ini_existing
+__missing__ = "#d30" ; @ini_missing
; site and sidebar widths
-__site_width__ = "75em"
-__sidebar_width__ = "16em"
+__site_width__ = "75em" ; @ini_site_width
+__sidebar_width__ = "16em" ; @ini_sidebar_width
; cut off points for mobile devices
-__tablet_width__ = "800px"
-__phone_width__ = "480px"
+__tablet_width__ = "800px" ; @ini_tablet_width
+__phone_width__ = "480px" ; @ini_phone_width