]> git.immae.eu Git - github/shaarli/Shaarli.git/commitdiff
Merge pull request #804 from ArthurHoaro/feature/atom-default
authorArthurHoaro <arthur@hoa.ro>
Tue, 21 Mar 2017 19:10:49 +0000 (20:10 +0100)
committerGitHub <noreply@github.com>
Tue, 21 Mar 2017 19:10:49 +0000 (20:10 +0100)
Fixes #304: use atom feed as default

28 files changed:
CHANGELOG.md
COPYING
README.md
application/NetscapeBookmarkUtils.php
application/config/ConfigJson.php
application/config/ConfigManager.php
composer.json
inc/awesomplete-multiple-tags.js
inc/plugin_admin.js
index.php
plugins/piwik/piwik.html
plugins/playvideos/youtube_playlist.js
plugins/qrcode/shaarli-qrcode.js
tests/NetscapeBookmarkUtils/BookmarkImportTest.php
tests/config/ConfigJsonTest.php
tests/utils/config/configJson.json.php
tpl/default/configure.html
tpl/default/css/shaarli.css
tpl/default/editlink.html
tpl/default/install.html
tpl/default/js/shaarli.js
tpl/default/linklist.html
tpl/default/loginform.html
tpl/default/page.footer.html
tpl/default/page.header.html
tpl/default/picwall.html
tpl/default/pluginsadmin.html
tpl/default/tools.html

index 1a87a8ca8ab712fa87ac75860228ca880f4d2b3e..f0813b97eafa3714c42369b391143333c3d2266c 100644 (file)
@@ -24,10 +24,13 @@ configuration to enable URL rewriting, see:
 Theming:
     - Introduce a new theme
     - Allow selecting themes/templates from the configuration page
+    - New/Edit link form can be submitted using CTRL+Enter in the textarea
+    - Shaarli version is displayed in the footer when logged in 
 - Add plugin placeholders to Atom/RSS feed templates
 - Add OpenSearch to feed templates
 - Add `campaign_` to the URL cleanup pattern list
 - Add an AUTHORS file and Makefile target to list authors from Git commit data
+- Link imports are now logged in `data/` folder, and can be debug using `dev.debug=true` setting.
 
 ### Changed
 - Docker: enable nginx URL rewriting for the REST API
@@ -35,6 +38,8 @@ Theming:
     - Move `user.css` to the `data` folder
     - Move default template files to a subfolder (`default`)
     - Rename the legacy theme to `vintage`
+    - Private only filter is now displayed as a search parameter
+    - Autocomplete: pre-select the first element
 - Move PubSubHub to a dedicated plugin
 - Coding style:
     - explicit method visibility
@@ -42,6 +47,9 @@ Theming:
     - remove unused variables
 - The updater now keeps custom theme preferences
 - Simplify the COPYING information
+- Improved client locale detection
+- Improved date time display depending on the locale
+- Partial namespace support for Shaarli classes
 
 ### Removed
 - PHP < 5.5 compatibility
@@ -57,6 +65,8 @@ Theming:
 - Fix redirection after link deletion
 - Do not access LinkDB links by ID before the Updater applies migrations
 - Remove extra spaces in the bookmarklet's name
+- Piwik plugin: Piwik URL protocol can now be set (http or https)
+- All inline JS has been moved to dedicated JS files
 
 ### Security
 - Markdown plugin: escape HTML entities by default
diff --git a/COPYING b/COPYING
index 4bbdf2b3c95bb18bf984bb0f6084793231bb40fb..0520215247e0c49e9d0e9e0dfcb17b227240a6c5 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -46,6 +46,10 @@ Files: plugins/wallabag/wallabag.png
 License: MIT License (http://opensource.org/licenses/MIT)
 Copyright: (C) 2015 Nicolas Lœuillet - https://github.com/wallabag/wallabag
 
+Files: tpl/default/sad_star.png
+License: MIT License (http://opensource.org/licenses/MIT)
+Copyright: (C) 2015 kalvn - https://github.com/kalvn/Shaarli-Material
+
 ----------------------------------------------------
 ZLIB/LIBPNG LICENSE
 
index 21062b9bd3a6351e1f81d5f2727c4c366349d435..db1b901f27a3ae7709fef55bfc420f306fb39b95 100644 (file)
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ _It is designed to be personal (single-user), fast and handy._
 - [Bugs/Feature requests/Discussion](https://github.com/shaarli/Shaarli/issues/)
 
 ### Demo
-You can use this [public demo instance of Shaarli](http://shaarlidemo.tuxfamily.org/Shaarli).
+You can use this [public demo instance of Shaarli](https://demo.shaarli.org).
 It runs the latest development version of Shaarli and is updated/reset daily.
 
 Login: `demo`; Password: `demo`
index e7148d005776c7c41df62e72e5cba237a6a6f753..ab346f81c2ada769d204ea79d8f5ed21efb90213 100644 (file)
@@ -1,7 +1,13 @@
 <?php
 
+use Psr\Log\LogLevel;
+use Shaarli\Config\ConfigManager;
+use Shaarli\NetscapeBookmarkParser\NetscapeBookmarkParser;
+use Katzgrau\KLogger\Logger;
+
 /**
  * Utilities to import and export bookmarks using the Netscape format
+ * TODO: Not static, use a container.
  */
 class NetscapeBookmarkUtils
 {
@@ -85,14 +91,14 @@ class NetscapeBookmarkUtils
     /**
      * Imports Web bookmarks from an uploaded Netscape bookmark dump
      *
-     * @param array  $post      Server $_POST parameters
-     * @param array  $files     Server $_FILES parameters
-     * @param LinkDB $linkDb    Loaded LinkDB instance
-     * @param string $pagecache Page cache
+     * @param array         $post      Server $_POST parameters
+     * @param array         $files     Server $_FILES parameters
+     * @param LinkDB        $linkDb    Loaded LinkDB instance
+     * @param ConfigManager $conf      instance
      *
      * @return string Summary of the bookmark import status
      */
-    public static function import($post, $files, $linkDb, $pagecache)
+    public static function import($post, $files, $linkDb, $conf)
     {
         $filename = $files['filetoupload']['name'];
         $filesize = $files['filetoupload']['size'];
@@ -119,10 +125,20 @@ class NetscapeBookmarkUtils
         $defaultPrivacy = 0;
 
         $parser = new NetscapeBookmarkParser(
-            true,                       // nested tag support
-            $defaultTags,               // additional user-specified tags
-            strval(1 - $defaultPrivacy) // defaultPub = 1 - defaultPrivacy
+            true,                           // nested tag support
+            $defaultTags,                   // additional user-specified tags
+            strval(1 - $defaultPrivacy),    // defaultPub = 1 - defaultPrivacy
+            $conf->get('resource.data_dir') // log path, will be overridden
+        );
+        $logger = new Logger(
+            $conf->get('resource.data_dir'),
+            ! $conf->get('dev.debug') ? LogLevel::INFO : LogLevel::DEBUG,
+            [
+                'prefix' => 'import.',
+                'extension' => 'log',
+            ]
         );
+        $parser->setLogger($logger);
         $bookmarks = $parser->parseString($data);
 
         $importCount = 0;
@@ -179,7 +195,7 @@ class NetscapeBookmarkUtils
             $importCount++;
         }
 
-        $linkDb->save($pagecache);
+        $linkDb->save($conf->get('resource.page_cache'));
         return self::importStatus(
             $filename,
             $filesize,
index 30908d90db436574f9585d20d6b437f29d56e363..9ef2ef562634bb346cf398b290093cbd02e66926 100644 (file)
@@ -21,8 +21,14 @@ class ConfigJson implements ConfigIO
         $data = str_replace(self::getPhpSuffix(), '', $data);
         $data = json_decode($data, true);
         if ($data === null) {
-            $error = json_last_error();
-            throw new \Exception('An error occurred while parsing JSON file: error code #'. $error);
+            $errorCode = json_last_error();
+            $error  = 'An error occurred while parsing JSON configuration file ('. $filepath .'): error code #';
+            $error .= $errorCode. '<br>➜ <code>' . json_last_error_msg() .'</code>';
+            if ($errorCode === JSON_ERROR_SYNTAX) {
+                $error .= '<br>Please check your JSON syntax (without PHP comment tags) using a JSON lint tool such as ';
+                $error .= '<a href="http://jsonlint.com/">jsonlint.com</a>.';
+            }
+            throw new \Exception($error);
         }
         return $data;
     }
index c5eeda08681728acbc0638aca8bff3737d184166..7bfbfc729fe4b67c153d8c5c367d1bd763d074f5 100644 (file)
@@ -81,7 +81,11 @@ class ConfigManager
      */
     protected function load()
     {
-        $this->loadedConfig = $this->configIO->read($this->getConfigFileExt());
+        try {
+            $this->loadedConfig = $this->configIO->read($this->getConfigFileExt());
+        } catch (\Exception $e) {
+            die($e->getMessage());
+        }
         $this->setDefaultValues();
     }
 
index 57851e53e27fbab99fa5044de0d0bf0c389a30a6..792c43d31cabf74652e6aecb04c768b1cdcf23fd 100644 (file)
@@ -11,7 +11,7 @@
     "keywords": ["bookmark", "link", "share", "web"],
     "require": {
         "php": ">=5.5",
-        "shaarli/netscape-bookmark-parser": "1.*",
+        "shaarli/netscape-bookmark-parser": "^2.0",
         "erusev/parsedown": "1.6",
         "slim/slim": "^3.0",
         "pubsubhubbub/publisher": "dev-master"
index faecb417858e3dd05487d5f3e7000f4d602a7bda..c38dc38ee809099531aa6a92a5c9d8385eece6da 100644 (file)
@@ -1,3 +1,31 @@
+/** @licstart  The following is the entire license notice for the
+ *  JavaScript code in this page.
+ *
+ *   Copyright: (c) 2011-2015 Sébastien SAUVAGE <sebsauvage@sebsauvage.net>
+ *              (c) 2011-2017 The Shaarli Community, see AUTHORS
+ *
+ *   This software is provided 'as-is', without any express or implied warranty.
+ *   In no event will the authors be held liable for any damages arising from
+ *   the use of this software.
+ *
+ *   Permission is granted to anyone to use this software for any purpose,
+ *   including commercial applications, and to alter it and redistribute it
+ *   freely, subject to the following restrictions:
+ *
+ *   1. The origin of this software must not be misrepresented; you must not
+ *   claim that you wrote the original software. If you use this software
+ *   in a product, an acknowledgment in the product documentation would
+ *   be appreciated but is not required.
+ *
+ *   2. Altered source versions must be plainly marked as such, and must
+ *   not be misrepresented as being the original software.
+ *
+ *   3. This notice may not be removed or altered from any source distribution.
+ *
+ *  @licend  The above is the entire license notice
+ *  for the JavaScript code in this page.
+ */
+
 var awp = Awesomplete.$;
 var autocompleteFields = document.querySelectorAll('input[data-multiple]');
 [].forEach.call(autocompleteFields, function(autocompleteField) {
index 055ac285a966c4203d588ee0e0f4a39537b3f1e3..4b55e0f3388d67a86d8ea6d6611a8abc288083d0 100644 (file)
@@ -1,3 +1,31 @@
+/** @licstart  The following is the entire license notice for the
+ *  JavaScript code in this page.
+ *
+ *   Copyright: (c) 2011-2015 Sébastien SAUVAGE <sebsauvage@sebsauvage.net>
+ *              (c) 2011-2017 The Shaarli Community, see AUTHORS
+ *
+ *   This software is provided 'as-is', without any express or implied warranty.
+ *   In no event will the authors be held liable for any damages arising from
+ *   the use of this software.
+ *
+ *   Permission is granted to anyone to use this software for any purpose,
+ *   including commercial applications, and to alter it and redistribute it
+ *   freely, subject to the following restrictions:
+ *
+ *   1. The origin of this software must not be misrepresented; you must not
+ *   claim that you wrote the original software. If you use this software
+ *   in a product, an acknowledgment in the product documentation would
+ *   be appreciated but is not required.
+ *
+ *   2. Altered source versions must be plainly marked as such, and must
+ *   not be misrepresented as being the original software.
+ *
+ *   3. This notice may not be removed or altered from any source distribution.
+ *
+ *  @licend  The above is the entire license notice
+ *  for the JavaScript code in this page.
+ */
+
 /**
  * Change the position counter of a row.
  *
index 3c2bb1d2829dee3a6a9d4e4b9edea6bacc5bd1ae..cc7f3ca3497feaf96288b61f718997eb0c3a09cf 100644 (file)
--- a/index.php
+++ b/index.php
@@ -1528,7 +1528,7 @@ function renderPage($conf, $pluginManager, $LINKSDB)
             $_POST,
             $_FILES,
             $LINKSDB,
-            $conf->get('resource.page_cache')
+            $conf
         );
         echo '<script>alert("'.$status.'");document.location=\'?do='
              .Router::$PAGE_IMPORT .'\';</script>';
index 0881d7c8fbd49fe5225667a0a0f65f7be7ad1529..f4bc358a7f7e2ead9c7c48a1aaaa1b3eb6c58f48 100644 (file)
@@ -1,5 +1,33 @@
 <!-- Piwik -->
 <script type="text/javascript">
+  /** @licstart  The following is the entire license notice for the
+   *  JavaScript code in this page.
+   *
+   *   Copyright: (c) 2011-2015 Sébastien SAUVAGE <sebsauvage@sebsauvage.net>
+   *              (c) 2011-2017 The Shaarli Community, see AUTHORS
+   *
+   *   This software is provided 'as-is', without any express or implied warranty.
+   *   In no event will the authors be held liable for any damages arising from
+   *   the use of this software.
+   *
+   *   Permission is granted to anyone to use this software for any purpose,
+   *   including commercial applications, and to alter it and redistribute it
+   *   freely, subject to the following restrictions:
+   *
+   *   1. The origin of this software must not be misrepresented; you must not
+   *   claim that you wrote the original software. If you use this software
+   *   in a product, an acknowledgment in the product documentation would
+   *   be appreciated but is not required.
+   *
+   *   2. Altered source versions must be plainly marked as such, and must
+   *   not be misrepresented as being the original software.
+   *
+   *   3. This notice may not be removed or altered from any source distribution.
+   *
+   *  @licend  The above is the entire license notice
+   *  for the JavaScript code in this page.
+   */
+
   var _paq = _paq || [];
   _paq.push(['trackPageView']);
   _paq.push(['enableLinkTracking']);
index be8d63afa49c751c9a6557e618abc7d619140ecf..3b608a5dfbf97549973ffb3170803b082e988249 100644 (file)
@@ -1,3 +1,31 @@
+/** @licstart  The following is the entire license notice for the
+ *  JavaScript code in this page.
+ *
+ *   Copyright: (c) 2011-2015 Sébastien SAUVAGE <sebsauvage@sebsauvage.net>
+ *              (c) 2011-2017 The Shaarli Community, see AUTHORS
+ *
+ *   This software is provided 'as-is', without any express or implied warranty.
+ *   In no event will the authors be held liable for any damages arising from
+ *   the use of this software.
+ *
+ *   Permission is granted to anyone to use this software for any purpose,
+ *   including commercial applications, and to alter it and redistribute it
+ *   freely, subject to the following restrictions:
+ *
+ *   1. The origin of this software must not be misrepresented; you must not
+ *   claim that you wrote the original software. If you use this software
+ *   in a product, an acknowledgment in the product documentation would
+ *   be appreciated but is not required.
+ *
+ *   2. Altered source versions must be plainly marked as such, and must
+ *   not be misrepresented as being the original software.
+ *
+ *   3. This notice may not be removed or altered from any source distribution.
+ *
+ *  @licend  The above is the entire license notice
+ *  for the JavaScript code in this page.
+ */
+
 var run_playideos = (function () {
     var e, n, t, o, r, i = [].indexOf || function (e) {
             for (var n = 0, t = this.length; n < t; n++) {
index 615f54c72c3cfe42e3a8df6b8d3aa3bfc9a46c1b..fe77c4cdc47cbb4ae36471513908e950adfe8d6d 100644 (file)
@@ -1,3 +1,31 @@
+/** @licstart  The following is the entire license notice for the
+ *  JavaScript code in this page.
+ *
+ *   Copyright: (c) 2011-2015 Sébastien SAUVAGE <sebsauvage@sebsauvage.net>
+ *              (c) 2011-2017 The Shaarli Community, see AUTHORS
+ *
+ *   This software is provided 'as-is', without any express or implied warranty.
+ *   In no event will the authors be held liable for any damages arising from
+ *   the use of this software.
+ *
+ *   Permission is granted to anyone to use this software for any purpose,
+ *   including commercial applications, and to alter it and redistribute it
+ *   freely, subject to the following restrictions:
+ *
+ *   1. The origin of this software must not be misrepresented; you must not
+ *   claim that you wrote the original software. If you use this software
+ *   in a product, an acknowledgment in the product documentation would
+ *   be appreciated but is not required.
+ *
+ *   2. Altered source versions must be plainly marked as such, and must
+ *   not be misrepresented as being the original software.
+ *
+ *   3. This notice may not be removed or altered from any source distribution.
+ *
+ *  @licend  The above is the entire license notice
+ *  for the JavaScript code in this page.
+ */
+
 // Show the QR-Code of a permalink (when the QR-Code icon is clicked).
 function showQrCode(caller,loading)
 { 
index 0ca07eacb7741e83aebb126e19502da62cbe5fee..5925a8e156865be6c3343ca0e6b937a08cb97cf0 100644 (file)
@@ -2,6 +2,7 @@
 
 require_once 'application/NetscapeBookmarkUtils.php';
 
+use Shaarli\Config\ConfigManager;
 
 /**
  * Utility function to load a file's metadata in a $_FILES-like array
@@ -42,6 +43,11 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
      */
     protected $pagecache = 'tests';
 
+    /**
+     * @var ConfigManager instance.
+     */
+    protected $conf;
+
     /**
      * @var string Save the current timezone.
      */
@@ -65,6 +71,8 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         // start with an empty datastore
         file_put_contents(self::$testDatastore, '<?php /* S7QysKquBQA= */ ?>');
         $this->linkDb = new LinkDB(self::$testDatastore, true, false);
+        $this->conf = new ConfigManager('tests/utils/config/configJson');
+        $this->conf->set('resource.page_cache', $this->pagecache);
     }
 
     public static function tearDownAfterClass()
@@ -81,7 +89,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(
             'File empty.htm (0 bytes) has an unknown file format.'
             .' Nothing was imported.',
-            NetscapeBookmarkUtils::import(NULL, $files, NULL, NULL)
+            NetscapeBookmarkUtils::import(NULL, $files, NULL, $this->conf)
         );
         $this->assertEquals(0, count($this->linkDb));
     }
@@ -94,7 +102,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         $files = file2array('no_doctype.htm');
         $this->assertEquals(
             'File no_doctype.htm (350 bytes) has an unknown file format. Nothing was imported.',
-            NetscapeBookmarkUtils::import(NULL, $files, NULL, NULL)
+            NetscapeBookmarkUtils::import(NULL, $files, NULL, $this->conf)
         );
         $this->assertEquals(0, count($this->linkDb));
     }
@@ -108,7 +116,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(
             'File internet_explorer_encoding.htm (356 bytes) was successfully processed:'
             .' 1 links imported, 0 links overwritten, 0 links skipped.',
-            NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->pagecache)
+            NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->conf)
         );
         $this->assertEquals(1, count($this->linkDb));
         $this->assertEquals(0, count_private($this->linkDb));
@@ -137,7 +145,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(
             'File netscape_nested.htm (1337 bytes) was successfully processed:'
             .' 8 links imported, 0 links overwritten, 0 links skipped.',
-            NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->pagecache)
+            NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->conf)
         );
         $this->assertEquals(8, count($this->linkDb));
         $this->assertEquals(2, count_private($this->linkDb));
@@ -259,7 +267,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(
             'File netscape_basic.htm (482 bytes) was successfully processed:'
             .' 2 links imported, 0 links overwritten, 0 links skipped.',
-            NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->pagecache)
+            NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->conf)
         );
 
         $this->assertEquals(2, count($this->linkDb));
@@ -304,7 +312,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(
             'File netscape_basic.htm (482 bytes) was successfully processed:'
             .' 2 links imported, 0 links overwritten, 0 links skipped.',
-            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache)
+            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
         );
         $this->assertEquals(2, count($this->linkDb));
         $this->assertEquals(1, count_private($this->linkDb));
@@ -348,7 +356,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(
             'File netscape_basic.htm (482 bytes) was successfully processed:'
             .' 2 links imported, 0 links overwritten, 0 links skipped.',
-            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache)
+            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
         );
         $this->assertEquals(2, count($this->linkDb));
         $this->assertEquals(0, count_private($this->linkDb));
@@ -372,7 +380,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(
             'File netscape_basic.htm (482 bytes) was successfully processed:'
             .' 2 links imported, 0 links overwritten, 0 links skipped.',
-            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache)
+            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
         );
         $this->assertEquals(2, count($this->linkDb));
         $this->assertEquals(2, count_private($this->linkDb));
@@ -398,7 +406,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(
             'File netscape_basic.htm (482 bytes) was successfully processed:'
             .' 2 links imported, 0 links overwritten, 0 links skipped.',
-            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache)
+            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
         );
         $this->assertEquals(2, count($this->linkDb));
         $this->assertEquals(2, count_private($this->linkDb));
@@ -418,7 +426,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(
             'File netscape_basic.htm (482 bytes) was successfully processed:'
             .' 2 links imported, 2 links overwritten, 0 links skipped.',
-            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache)
+            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
         );
         $this->assertEquals(2, count($this->linkDb));
         $this->assertEquals(0, count_private($this->linkDb));
@@ -444,7 +452,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(
             'File netscape_basic.htm (482 bytes) was successfully processed:'
             .' 2 links imported, 0 links overwritten, 0 links skipped.',
-            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache)
+            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
         );
         $this->assertEquals(2, count($this->linkDb));
         $this->assertEquals(0, count_private($this->linkDb));
@@ -465,7 +473,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(
             'File netscape_basic.htm (482 bytes) was successfully processed:'
             .' 2 links imported, 2 links overwritten, 0 links skipped.',
-            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache)
+            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
         );
         $this->assertEquals(2, count($this->linkDb));
         $this->assertEquals(2, count_private($this->linkDb));
@@ -489,7 +497,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(
             'File netscape_basic.htm (482 bytes) was successfully processed:'
             .' 2 links imported, 0 links overwritten, 0 links skipped.',
-            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache)
+            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
         );
         $this->assertEquals(2, count($this->linkDb));
         $this->assertEquals(0, count_private($this->linkDb));
@@ -499,7 +507,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(
             'File netscape_basic.htm (482 bytes) was successfully processed:'
             .' 0 links imported, 0 links overwritten, 2 links skipped.',
-            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache)
+            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
         );
         $this->assertEquals(2, count($this->linkDb));
         $this->assertEquals(0, count_private($this->linkDb));
@@ -518,7 +526,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(
             'File netscape_basic.htm (482 bytes) was successfully processed:'
             .' 2 links imported, 0 links overwritten, 0 links skipped.',
-            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache)
+            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
         );
         $this->assertEquals(2, count($this->linkDb));
         $this->assertEquals(0, count_private($this->linkDb));
@@ -545,7 +553,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(
             'File netscape_basic.htm (482 bytes) was successfully processed:'
             .' 2 links imported, 0 links overwritten, 0 links skipped.',
-            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache)
+            NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
         );
         $this->assertEquals(2, count($this->linkDb));
         $this->assertEquals(0, count_private($this->linkDb));
@@ -570,7 +578,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(
             'File same_date.htm (453 bytes) was successfully processed:'
             .' 3 links imported, 0 links overwritten, 0 links skipped.',
-            NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->pagecache)
+            NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->conf)
         );
         $this->assertEquals(3, count($this->linkDb));
         $this->assertEquals(0, count_private($this->linkDb));
index 3527f83d67af1bae0816f61ea8bd164d1cfb4b99..d237bc80cdacd1a7919399f68cad57ece869a470 100644 (file)
@@ -40,7 +40,7 @@ class ConfigJsonTest extends \PHPUnit_Framework_TestCase
      * Read a non existent config file -> empty array.
      *
      * @expectedException \Exception
-     * @expectedExceptionMessage An error occurred while parsing JSON file: error code #4
+     * @expectedExceptionMessageRegExp  /An error occurred while parsing JSON configuration file \([\w\/\.]+\): error code #4/
      */
     public function testReadInvalidJson()
     {
index 13d38c6680b4a4515192ee0045adcfea05c45b0e..9c9288f30cc696c38115dd1562a1770b3dfe8cb3 100644 (file)
@@ -24,7 +24,7 @@
     },
     "resource": {
         "datastore": "tests\/utils\/config\/datastore.php",
-        "data_dir": "tests\/utils\/config",
+        "data_dir": "sandbox/",
         "raintpl_tpl": "tpl/"
     },
     "plugins": {
index 2f54a0851157ff01d37903fbf8878924936a0cff..d6536d47509a5228bda5e1acbc70a32069735f35 100644 (file)
@@ -55,7 +55,7 @@
         </div>
         <div class="pure-u-lg-{$ratioInput} pure-u-1">
           <div class="form-input">
-            <select name="theme" id="theme">
+            <select name="theme" id="theme" class="align">
               {loop="$theme_available"}
                 <option value="{$value}"
                   {if="$value===$theme"}
 </form>
 
 {include="page.footer"}
-
-<script>
-  (function (window, document) {
-    var toRemove = document.getElementById('timezone-remove');
-    var firstSelect = toRemove.getElementsByTagName('select')[0];
-    var secondSelect = toRemove.getElementsByTagName('select')[1];
-    toRemove.parentNode.removeChild(toRemove);
-    var toAdd = document.getElementById('timezone-add');
-    var newTimezone = '<span class="timezone-continent">Continent ' + firstSelect.outerHTML + '</span>';
-    newTimezone += ' <span class="timezone-country">Country ' + secondSelect.outerHTML + '</span>';
-    toAdd.innerHTML = newTimezone;
-  })(this, this.document);
-</script>
 </body>
 </html>
 
index d33e906683a956a57e9b97a2b59b8104eb551770..8fcd13afdad80956789f8842e329ef1d3ac1233e 100644 (file)
@@ -832,6 +832,7 @@ pre {
 
 .page-form-complete .form-label label,
 .page-form-complete .form-input input,
+.page-form-complete .form-input select.align,
 .page-form-complete .timezone {
     position: absolute;
     top: 50%;
@@ -908,6 +909,10 @@ div.awesomplete > ul {
     color: black;
 }
 
+form[name="linkform"].page-form {
+    overflow: visible;
+}
+
 @media screen and (max-width: 64em) {
     .page-form-complete .form-label {
         height: inherit;
index 2180c080aa4467f8ba5fd8ffc5e489f107c5f056..354499a4121376d8e143a073f1f53603531bc2ef 100644 (file)
@@ -4,11 +4,7 @@
   {include="includes"}
 </head>
 <body>
-  {if="$source !== 'firefoxsocialapi' && $source !== 'bookmarklet'"}
-    {include="page.header"}
-  {else}
-    <div class="center">Shaare to: {$shaarlititle}</div>
-  {/if}
+  {include="page.header"}
   <div id="editlinkform" class="pure-g">
     <div class="pure-u-lg-1-5 pure-u-1-24"></div>
     <form method="post" name="linkform" class="page-form pure-u-lg-3-5 pure-u-22-24 page-form page-form-light">
         <label for="lf_url">{'URL'|t}</label>
       </div>
       <div>
-        <input type="text" name="lf_url" id="lf_url" value="{$link.url}" class="lf_input">
+        <input type="text" name="lf_url" id="lf_url" value="{$link.url}" class="lf_input autofocus">
       </div>
       <div>
       <label for="lf_title">{'Title'|t}</label>
       </div>
       <div>
-        <input type="text" name="lf_title" id="lf_title" value="{$link.title}" class="lf_input">
+        <input type="text" name="lf_title" id="lf_title" value="{$link.title}" class="lf_input autofocus">
       </div>
       <div>
         <label for="lf_description">{'Description'|t}</label>
       </div>
       <div>
-        <textarea name="lf_description" id="lf_description">{$link.description}</textarea>
+        <textarea name="lf_description" id="lf_description" class="autofocus">{$link.description}</textarea>
       </div>
       <div>
         <label for="lf_tags">{'Tags'|t}</label>
       </div>
       <div>
-        <input type="text" name="lf_tags" id="lf_tags" value="{$link.tags}" class="lf_input"
-          data-list="{loop="$tags"}{$key}, {/loop}" data-multiple autocomplete="off" >
+        <input type="text" name="lf_tags" id="lf_tags" value="{$link.tags}" class="lf_input autofocus"
+          data-list="{loop="$tags"}{$key}, {/loop}" data-multiple data-autofirst autocomplete="off" >
       </div>
 
       <div>
       {/if}
     </form>
   </div>
-  {if="$source !== 'firefoxsocialapi' && $source !== 'bookmarklet'"}
-    {include="page.footer"}
-  {/if}
-<script>
-  awesompleteUniqueTag('#lf_tags');
-  if (!document.linkform.lf_title.value) {
-    document.linkform.lf_title.focus();
-  } else if (!document.linkform.lf_description.value) {
-    document.linkform.lf_description.focus();
-  } else {
-    document.linkform.lf_tags.focus();
-  }
-</script>
+  {include="page.footer"}
 </body>
 </html>
index 0bd8a63559b1b5146132fedea3f3d6f69d287f6c..33f8a45336c4a448505001dbce93d55f88261f34 100644 (file)
 </div>
 </form>
 {include="page.footer"}
-<script>
-  // FIXME!
-  (function (window, document) {
-    var toRemove = document.getElementById('timezone-remove');
-    var firstSelect = toRemove.getElementsByTagName('select')[0];
-    var secondSelect = toRemove.getElementsByTagName('select')[1];
-    toRemove.parentNode.removeChild(toRemove);
-    var toAdd = document.getElementById('timezone-add');
-    var newTimezone = '<span class="timezone-continent">Continent ' + firstSelect.outerHTML + '</span>';
-    newTimezone += ' <span class="timezone-country">Country ' + secondSelect.outerHTML + '</span>';
-    toAdd.innerHTML = newTimezone;
-  })(this, this.document);
-</script>
 </body>
 </html>
index f7de0a49894ae84a35e68cb48f34829b349deddc..30d8ed6ff73482f9502e03268e321c3643aa0726 100644 (file)
@@ -1,3 +1,31 @@
+/** @licstart  The following is the entire license notice for the
+ *  JavaScript code in this page.
+ *
+ *   Copyright: (c) 2011-2015 Sébastien SAUVAGE <sebsauvage@sebsauvage.net>
+ *              (c) 2011-2017 The Shaarli Community, see AUTHORS
+ *
+ *   This software is provided 'as-is', without any express or implied warranty.
+ *   In no event will the authors be held liable for any damages arising from
+ *   the use of this software.
+ *
+ *   Permission is granted to anyone to use this software for any purpose,
+ *   including commercial applications, and to alter it and redistribute it
+ *   freely, subject to the following restrictions:
+ *
+ *   1. The origin of this software must not be misrepresented; you must not
+ *   claim that you wrote the original software. If you use this software
+ *   in a product, an acknowledgment in the product documentation would
+ *   be appreciated but is not required.
+ *
+ *   2. Altered source versions must be plainly marked as such, and must
+ *   not be misrepresented as being the original software.
+ *
+ *   3. This notice may not be removed or altered from any source distribution.
+ *
+ *  @licend  The above is the entire license notice
+ *  for the JavaScript code in this page.
+ */
+
 window.onload = function () {
 
     /**
@@ -185,9 +213,13 @@ window.onload = function () {
     /**
      * Autofocus text fields
      */
-    var autofocusElements = document.querySelector('.autofocus');
-    if (autofocusElements != null) {
-        autofocusElements.focus();
+    // ES6 syntax
+    let autofocusElements = document.querySelectorAll('.autofocus');
+    for (let autofocusElement of autofocusElements) {
+        if (autofocusElement.value == '') {
+            autofocusElement.focus();
+            break;
+        }
     }
 
     /**
@@ -266,4 +298,96 @@ window.onload = function () {
             }
         });
     }
+
+    /**
+     * TimeZome select
+     * FIXME! way too hackish
+     */
+    var toRemove = document.getElementById('timezone-remove');
+    if (toRemove != null) {
+        var firstSelect = toRemove.getElementsByTagName('select')[0];
+        var secondSelect = toRemove.getElementsByTagName('select')[1];
+        toRemove.parentNode.removeChild(toRemove);
+        var toAdd = document.getElementById('timezone-add');
+        var newTimezone = '<span class="timezone-continent">Continent ' + firstSelect.outerHTML + '</span>';
+        newTimezone += ' <span class="timezone-country">Country ' + secondSelect.outerHTML + '</span>';
+        toAdd.innerHTML = newTimezone;
+    }
+
+    /**
+     * Awesomplete trigger.
+     */
+    var tags = document.getElementById('lf_tags');
+    if (tags != null) {
+        awesompleteUniqueTag('#lf_tags');
+    }
+
+    /**
+     * bLazy trigger
+     */
+    var picwall = document.getElementById('picwall_container');
+    if (picwall != null) {
+        var bLazy = new Blazy();
+    }
+
+    /**
+     * Bookmarklet alert
+     */
+    var bookmarkletLinks = document.querySelectorAll('.bookmarklet-link');
+    var bkmMessage = document.getElementById('bookmarklet-alert');
+    [].forEach.call(bookmarkletLinks, function(link) {
+        link.addEventListener('click', function(event) {
+            event.preventDefault();
+            alert(bkmMessage.value);
+        });
+    });
+
+    /**
+     * Firefox Social
+     */
+    var ffButton = document.getElementById('ff-social-button');
+    if (ffButton != null) {
+        ffButton.addEventListener('click', function(event) {
+            activateFirefoxSocial(event.target);
+        });
+    }
+
+    /**
+     * Plugin admin order
+     */
+    var orderPA = document.querySelectorAll('.order');
+    [].forEach.call(orderPA, function(link) {
+        link.addEventListener('click', function(event) {
+            event.preventDefault();
+            if (event.target.classList.contains('order-up')) {
+                return orderUp(event.target.parentNode.parentNode.getAttribute('data-order'));
+            } else if (event.target.classList.contains('order-down')) {
+                return orderDown(event.target.parentNode.parentNode.getAttribute('data-order'));
+            }
+        });
+    });
 };
+
+function activateFirefoxSocial(node) {
+    var loc = location.href;
+    var baseURL = loc.substring(0, loc.lastIndexOf("/"));
+
+    // Keeping the data separated (ie. not in the DOM) so that it's maintainable and diffable.
+    var data = {
+        name: "{$shaarlititle}",
+        description: "The personal, minimalist, super-fast, database free, bookmarking service by the Shaarli community.",
+        author: "Shaarli",
+        version: "1.0.0",
+
+        iconURL: baseURL + "/images/favicon.ico",
+        icon32URL: baseURL + "/images/favicon.ico",
+        icon64URL: baseURL + "/images/favicon.ico",
+
+        shareURL: baseURL + "{noparse}?post=%{url}&title=%{title}&description=%{text}&source=firefoxsocialapi{/noparse}",
+        homepageURL: baseURL
+    };
+    node.setAttribute("data-service", JSON.stringify(data));
+
+    var activate = new CustomEvent("ActivateSocialFeature");
+    node.dispatchEvent(activate);
+}
index 94370203bf2b2b8cf0fe014129569db4907b2008..57ef4567a8ee754c1f308c3b153e6d0188223b86 100644 (file)
@@ -34,7 +34,7 @@
                {if="!empty($search_tags)"}
                value="{$search_tags}"
                {/if}
-        autocomplete="off" data-multiple data-minChars="1"
+        autocomplete="off" data-multiple data-autofirst data-minChars="1"
         data-list="{loop="$tags"}{$key}, {/loop}"
         >
         <button type="submit" class="search-button"><i class="fa fa-search"></i></button>
index 2ad3fe9cdc8e5e0813895d7527126f1bb010e442..eb6d83781817690374ad593d4457eaf0fdd60401 100644 (file)
@@ -26,7 +26,7 @@
              {if="!empty($username)"}value="{$username}"{/if} class="autofocus" tabindex="20">
         </div>
         <div>
-          <input type="password" name="password" placeholder="{'Password'|t}" tabindex="21">
+          <input type="password" name="password" placeholder="{'Password'|t}" class="autofocus" tabindex="21">
         </div>
         <div class="remember-me">
           <input type="checkbox" name="longlastingsession" id="longlastingsessionform"
 {/if}
 
 {include="page.footer"}
-<script>
-  {if="ban_canLogin($conf) && ! empty($username)"}
-    // Focus password on load if the username is set.
-    var passwords = document.getElementsByName('password');
-    if (passwords.length == 2) {
-        passwords[1].focus();
-    }
-  {/if}
-</script>
 </body>
 </html>
 
index f7b80b68647c14553d3415a70b94476bb64247aa..77fc65dd9630feef1520b28c43569f18d13f8b85 100644 (file)
@@ -3,7 +3,11 @@
 <div class="pure-g">
   <div class="pure-u-2-24"></div>
   <div id="footer" class="pure-u-20-24">
-    <strong><a href="https://github.com/shaarli/Shaarli">Shaarli</a></strong> &middot;
+    <strong><a href="https://github.com/shaarli/Shaarli">Shaarli</a></strong>
+    {if="isLoggedIn()===true"}
+      {$version}
+    {/if}
+    &middot;
     The personal, minimalist, super-fast, database free, bookmarking service by the Shaarli community &middot;
     <a href="doc/Home.html" rel="nofollow">Documentation</a>
       {loop="$plugins_footer.text"}
index 04f33ea2377e7675832612bd210dd73330c391ba..9388ef79e9cdc42ca3e1b9c288a21df91d4255ce 100644 (file)
@@ -2,7 +2,7 @@
   <div class="pure-u-lg-0 pure-u-1">
     <div class="pure-menu">
       <a href="{$titleLink}" class="pure-menu-link">
-        <i class="fa fa-home"></i>
+        <img src="img/icon.png" width="16" height="16" class="head-logo" alt="logo" />
         {$shaarlititle}
       </a>
       <a href="#" class="menu-toggle" id="menu-toggle"><s class="bar"></s><s class="bar"></s></a>
                  {if="!empty($search_tags)"}
                  value="{$search_tags}"
                  {/if}
-          autocomplete="off" data-multiple data-minChars="1"
+          autocomplete="off" data-multiple data-autofirst data-minChars="1"
           data-list="{loop="$tags"}{$key}, {/loop}"
           >
           <button type="submit" class="search-button"><i class="fa fa-search"></i></button>
index b9ae2f2e5d2f007acc33c6e018d8e2d2c8e5dd9d..248e56df78345029b8439b335911b27bf56ad2e3 100644 (file)
 
 {include="page.footer"}
 <script src="inc/blazy-1.3.1.min.js#"></script>
-<script>
-  window.onload = function() {
-    var bLazy = new Blazy();
-  }
-</script>
 </body>
 </html>
 
index 92af2eefd63bf9ccf6a7f558b5455a9bc8de8383..5cc1802f77dff26790ced7d1c77ce52c176c7438 100644 (file)
                   <td><div class="pure-u-0 pure-u-lg-visible"><label for="{$key}">{$value.description}</label></div></td>
                   <td class="center">
                     {if="count($enabledPlugins)>1"}
-                    <a href="#" class="order"
-                       onclick="return orderUp(this.parentNode.parentNode.getAttribute('data-order'));">
-                      ▲
-                    </a>
-                    <a href="#" class="order"
-                       onclick="return orderDown(this.parentNode.parentNode.getAttribute('data-order'));">
-                      ▼
-                    </a>
+                    <a href="#" class="order order-up">▲</a>
+                    <a href="#" class="order order-down">▼</a>
                     {/if}
                     <input type="hidden" name="order_{$key}" value="{$counter}">
                   </td>
index b9df32d9ee31ca8bdd386f58a5c60ef253e976a4..baa033aff7cb0b22cbaed714b2b04f99fd17052f 100644 (file)
@@ -67,7 +67,7 @@
     <div class="tools-item">
       <a title="{'Drag this link to your bookmarks toolbar or right-click it and Bookmark This Link'|t},
                 {'then click ✚Shaare link button in any page you want to share'|t}"
-         onclick="return alertBookmarklet();"
+         class="bookmarklet-link"
          href="javascript:(
           function(){
             var%20url%20=%20location.href;
@@ -86,8 +86,8 @@
     <div class="tools-item">
       <a title="{'Drag this link to your bookmarks toolbar or right-click it and Bookmark This Link'|t},
                 {'Then click ✚Add Note button anytime to start composing a private Note (text post) to your Shaarli'|t}"
-         onclick="return alertBookmarklet();"
-         href="?private=1&amp;post=">
+         href="?private=1&amp;post="
+         class="bookmarklet-link">
         <span class="pure-button pure-u-lg-2-3 pure-u-3-4">✚ {'Add Note'|t}</span>
       </a>
     </div>
 
       <div class="tools-item">
         <a title="{'Click on this button to add Shaarli to the 'Share this page' button in Firefox"
-           onclick="activateFirefoxSocial(this)">
+           id="ff-social-button">
         <span class="pure-button pure-u-lg-2-3 pure-u-3-4">✚ {'Add to'|t} Firefox Social</span>
         </a>
       </div>
 </div>
 
 {include="page.footer"}
-
-<script>
-  {if="$sslenabled"}
-    function activateFirefoxSocial(node) {
-      var loc = location.href;
-      var baseURL = loc.substring(0, loc.lastIndexOf("/"));
-
-      // Keeping the data separated (ie. not in the DOM) so that it's maintainable and diffable.
-      var data = {
-        name: "{$shaarlititle}",
-        description: "The personal, minimalist, super-fast, database free, bookmarking service by the Shaarli community.",
-        author: "Shaarli",
-        version: "1.0.0",
-
-        iconURL: baseURL + "/images/favicon.ico",
-        icon32URL: baseURL + "/images/favicon.ico",
-        icon64URL: baseURL + "/images/favicon.ico",
-
-        shareURL: baseURL + "{noparse}?post=%{url}&title=%{title}&description=%{text}&source=firefoxsocialapi{/noparse}",
-        homepageURL: baseURL
-      };
-      node.setAttribute("data-service", JSON.stringify(data));
-
-      var activate = new CustomEvent("ActivateSocialFeature");
-      node.dispatchEvent(activate);
-    }
-  {/if}
-  function alertBookmarklet() {
-    alert({"'Drag this link to your bookmarks toolbar, or right-click it and choose Bookmark This Link'"|t});
-    return false;
-  }
-</script>
+<input type="hidden" id="bookmarklet-alert"
+       value="{'Drag this link to your bookmarks toolbar, or right-click it and choose Bookmark This Link'|t}">
 </body>
 </html>