index index.html index.php;
server {
- listen 80;
- root /var/www/shaarli;
+ listen 80;
+ root /var/www/shaarli;
access_log /var/log/nginx/shaarli.access.log;
error_log /var/log/nginx/shaarli.error.log;
- location ~ /\. {
- # deny access to dotfiles
- access_log off;
- log_not_found off;
- deny all;
- }
-
- location ~ ~$ {
- # deny access to temp editor files, e.g. "script.php~"
- access_log off;
- log_not_found off;
- deny all;
- }
-
- location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
+ location ~* \.(?:ico|css|js|gif|jpe?g|png|ttf|oet|woff2?)$ {
# cache static assets
expires max;
add_header Pragma public;
alias /var/www/shaarli/images/favicon.ico;
}
+ location /doc/html/ {
+ default_type "text/html";
+ try_files $uri $uri/ $uri.html =404;
+ }
+
location / {
- # Slim - rewrite URLs
- try_files $uri /index.php$is_args$args;
+ # Slim - rewrite URLs & do NOT serve static files through this location
+ try_files _ /index.php$is_args$args;
}
- location ~ (index)\.php$ {
+ location ~ index\.php$ {
# Slim - split URL path into (script_filename, path_info)
try_files $uri =404;
- fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_split_path_info ^(index.php)(/.+)$;
# filter and proxy PHP requests to PHP-FPM
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_index index.php;
include fastcgi.conf;
}
-
- location ~ /doc/ {
- default_type "text/html";
- try_files $uri $uri/ $uri.html =404;
- }
-
- location ~ \.php$ {
- # deny access to all other PHP scripts
- deny all;
- }
}
}
.dev
.git
.github
+.gitattributes
+.gitignore
+.travis.yml
tests
+# Docker related resources are not needed inside the container
+.dockerignore
+Dockerfile
+Dockerfile.armhf
+
# Docker Compose resources
docker-compose.yml
pagecache/*
tmp/*
+# Shaarli's docs are created during the build
+doc/html/
+
# Eclipse project files
.settings
.buildpath
# Alternative (if the 2 lines above don't work)
# SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0
-# REST API
+# Slim URL Redirection
# Ionos Hosting needs RewriteBase /
# RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
$this->setEmpty('general.enable_async_metadata', true);
$this->setEmpty('general.tags_separator', ' ');
- $this->setEmpty('updates.check_updates', false);
- $this->setEmpty('updates.check_updates_branch', 'stable');
+ $this->setEmpty('updates.check_updates', true);
+ $this->setEmpty('updates.check_updates_branch', 'latest');
$this->setEmpty('updates.check_updates_interval', 86400);
$this->setEmpty('feed.rss_permalinks', true);
*/
public function index(Request $request, Response $response): Response
{
- $latestVersion = 'v' . ApplicationUtils::getVersion(
- ApplicationUtils::$GIT_RAW_URL . '/latest/' . ApplicationUtils::$VERSION_FILE
- );
+ $releaseUrl = ApplicationUtils::$GITHUB_URL . '/releases/';
+ if ($this->container->conf->get('updates.check_updates', true)) {
+ $latestVersion = 'v' . ApplicationUtils::getVersion(
+ ApplicationUtils::$GIT_RAW_URL . '/latest/' . ApplicationUtils::$VERSION_FILE
+ );
+ $releaseUrl .= 'tag/' . $latestVersion;
+ } else {
+ $latestVersion = t('Check disabled');
+ }
+
$currentVersion = ApplicationUtils::getVersion('./shaarli_version.php');
$currentVersion = $currentVersion === 'dev' ? $currentVersion : 'v' . $currentVersion;
$phpEol = new \DateTimeImmutable(ApplicationUtils::getPhpEol(PHP_VERSION));
$this->assignView('php_has_reached_eol', $phpEol < new \DateTimeImmutable());
$this->assignView('php_extensions', ApplicationUtils::getPhpExtensionsRequirement());
$this->assignView('permissions', ApplicationUtils::checkResourcePermissions($this->container->conf));
- $this->assignView('release_url', ApplicationUtils::$GITHUB_URL . '/releases/tag/' . $latestVersion);
+ $this->assignView('release_url', $releaseUrl);
$this->assignView('latest_version', $latestVersion);
$this->assignView('current_version', $currentVersion);
$this->assignView('thumbnails_mode', $this->container->conf->get('thumbnails.mode'));
float: left;
}
+ul.warnings {
+ color: orange;
+ float: left;
+}
+
+ul.successes {
+ color: green;
+ float: left;
+}
+
#pluginsadmin {
width: 80%;
padding: 20px 0 0 20px;
width: 0%;
height: 10px;
}
+
+.loading-input {
+ position: relative;
+}
+
+@keyframes around {
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+.loading-input .icon-container {
+ position: absolute;
+ right: 60px;
+ top: calc(50% - 10px);
+}
+
+.loading-input .loader {
+ position: relative;
+ height: 20px;
+ width: 20px;
+ display: inline-block;
+ animation: around 5.4s infinite;
+}
+
+.loading-input .loader::after,
+.loading-input .loader::before {
+ content: "";
+ background: #eee;
+ position: absolute;
+ display: inline-block;
+ width: 100%;
+ height: 100%;
+ border-width: 2px;
+ border-color: #333 #333 transparent transparent;
+ border-style: solid;
+ border-radius: 20px;
+ box-sizing: border-box;
+ top: 0;
+ left: 0;
+ animation: around 0.7s ease-in-out infinite;
+}
+
+.loading-input .loader::after {
+ animation: around 0.7s ease-in-out 0.1s infinite;
+ background: transparent;
+}
+
# Docker
[Docker](https://docs.docker.com/get-started/overview/) is an open platform for developing, shipping, and running applications
# Download the latest version of Shaarli's docker-compose.yml
$ curl -L https://raw.githubusercontent.com/shaarli/Shaarli/latest/docker-compose.yml -o docker-compose.yml
# Create the .env file and fill in your VPS and domain information
-# (replace <MY_SHAARLI_DOMAIN> and <MY_CONTACT_EMAIL> with your actual information)
+# (replace <shaarli.mydomain.org>, <admin@mydomain.org> and <latest> with your actual information)
$ echo 'SHAARLI_VIRTUAL_HOST=shaarli.mydomain.org' > .env
$ echo 'SHAARLI_LETSENCRYPT_EMAIL=admin@mydomain.org' >> .env
+# Available Docker tags can be found at https://hub.docker.com/r/shaarli/shaarli/tags
+$ echo 'SHAARLI_DOCKER_TAG=latest' >> .env
# Pull the Docker images
$ docker-compose pull
# Run!
- [docker pull](https://docs.docker.com/engine/reference/commandline/pull/)
- [docker run](https://docs.docker.com/engine/reference/commandline/run/)
- [docker-compose logs](https://docs.docker.com/compose/reference/logs/)
-- Træfik: [Getting Started](https://docs.traefik.io/), [Docker backend](https://docs.traefik.io/configuration/backends/docker/), [Let's Encrypt](https://docs.traefik.io/user-guide/docker-and-lets-encrypt/), [Docker image](https://hub.docker.com/_/traefik/)
\ No newline at end of file
+- Træfik: [Getting Started](https://docs.traefik.io/), [Docker backend](https://docs.traefik.io/configuration/backends/docker/), [Let's Encrypt](https://docs.traefik.io/user-guide/docker-and-lets-encrypt/), [Docker image](https://hub.docker.com/_/traefik/)
Require all granted
</Directory>
- <LocationMatch "/\.">
- # Prevent accessing dotfiles
- RedirectMatch 404 ".*"
- </LocationMatch>
+ # BE CAREFUL: directives order matter!
- <LocationMatch "\.(?:ico|css|js|gif|jpe?g|png)$">
+ <FilesMatch ".*\.(?!(ico|css|js|gif|jpe?g|png|ttf|oet|woff2?)$)[^\.]*$">
+ Require all denied
+ </FilesMatch>
+
+ <Files "index.php">
+ Require all granted
+ </Files>
+
+ <FilesMatch "\.(?:ico|css|js|gif|jpe?g|png|ttf|oet|woff2)$">
# allow client-side caching of static files
Header set Cache-Control "max-age=2628000, public, must-revalidate, proxy-revalidate"
- </LocationMatch>
+ </FilesMatch>
+
# serve the Shaarli favicon from its custom location
Alias favicon.ico /var/www/shaarli.mydomain.org/images/favicon.ico
-
</VirtualHost>
```
location / {
# default index file when no file URI is requested
index index.php;
- try_files $uri /index.php$is_args$args;
+ try_files _ /index.php$is_args$args;
}
location ~ (index)\.php$ {
include fastcgi.conf;
}
- location ~ \.php$ {
- # deny access to all other PHP scripts
- # disable this if you host other PHP applications on the same virtualhost
- deny all;
- }
-
- location ~ /\. {
- # deny access to dotfiles
- deny all;
- }
-
- location ~ ~$ {
- # deny access to temp editor files, e.g. "script.php~"
- deny all;
- }
-
- location ~ /doc/ {
+ location ~ /doc/html/ {
default_type "text/html";
try_files $uri $uri/ $uri.html =404;
}
}
# allow client-side caching of static files
- location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
+ location ~* \.(?:ico|css|js|gif|jpe?g|png|ttf|oet|woff2?)$ {
expires max;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
# HTTP 1.0 compatibility
add_header Pragma public;
}
-
}
```
# Shaarli - Docker Compose example configuration
#
# See:
-# - https://shaarli.readthedocs.io/en/master/docker/shaarli-images/
-# - https://shaarli.readthedocs.io/en/master/guides/install-shaarli-with-debian9-and-docker/
+# - https://shaarli.readthedocs.io/en/master/Docker/#docker-compose
#
# Environment variables:
# - SHAARLI_VIRTUAL_HOST Fully Qualified Domain Name for the Shaarli instance
# - SHAARLI_LETSENCRYPT_EMAIL Contact email for certificate renewal
+# - SHAARLI_DOCKER_TAG Shaarli docker tag to use
+# See: https://hub.docker.com/r/shaarli/shaarli/tags
version: '3'
networks:
services:
shaarli:
- image: shaarli/shaarli:master
+ image: shaarli/shaarli:${SHAARLI_DOCKER_TAG}
build: ./
networks:
- http-proxy
- "--entrypoints=Name:https Address::443 TLS"
- "--retry"
- "--docker"
- - "--docker.domain=docker.localhost"
+ - "--docker.domain=${SHAARLI_VIRTUAL_HOST}"
- "--docker.exposedbydefault=true"
- "--docker.watch=true"
- "--acme"
msgid ""
msgstr ""
"Project-Id-Version: Shaarli\n"
-"POT-Creation-Date: 2020-11-05 19:43+0100\n"
-"PO-Revision-Date: 2020-11-05 19:44+0100\n"
+"POT-Creation-Date: 2020-11-09 14:39+0100\n"
+"PO-Revision-Date: 2020-11-09 14:42+0100\n"
"Last-Translator: \n"
"Language-Team: Shaarli\n"
"Language: fr_FR\n"
#: application/bookmark/BookmarkInitializer.php:91
#: application/legacy/LegacyLinkDB.php:246
#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15
-#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:50
+#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48
#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:15
-#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:50
+#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:48
msgid ""
"The personal, minimalist, super-fast, database free, bookmarking service"
msgstr ""
msgstr "Vous avez activé ou changé le mode de miniatures."
#: application/front/controller/admin/ConfigureController.php:103
-#: application/front/controller/admin/ServerController.php:68
+#: application/front/controller/admin/ServerController.php:75
#: application/legacy/LegacyUpdater.php:538
msgid "Please synchronize them."
msgstr "Merci de les synchroniser."
"le serveur web peut accepter (%s). Merci de l'envoyer en parties plus "
"légères."
-#: application/front/controller/admin/ManageTagController.php:29
+#: application/front/controller/admin/ManageTagController.php:30
+msgid "whitespace"
+msgstr "espace"
+
+#: application/front/controller/admin/ManageTagController.php:35
#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42
msgid "Manage tags"
msgstr "Gérer les tags"
-#: application/front/controller/admin/ManageTagController.php:48
+#: application/front/controller/admin/ManageTagController.php:54
msgid "Invalid tags provided."
msgstr "Les tags fournis ne sont pas valides."
-#: application/front/controller/admin/ManageTagController.php:72
+#: application/front/controller/admin/ManageTagController.php:78
#, php-format
msgid "The tag was removed from %d bookmark."
msgid_plural "The tag was removed from %d bookmarks."
msgstr[0] "Le tag a été supprimé du %d lien."
msgstr[1] "Le tag a été supprimé de %d liens."
-#: application/front/controller/admin/ManageTagController.php:77
+#: application/front/controller/admin/ManageTagController.php:83
#, php-format
msgid "The tag was renamed in %d bookmark."
msgid_plural "The tag was renamed in %d bookmarks."
msgstr[0] "Le tag a été renommé dans %d lien."
msgstr[1] "Le tag a été renommé dans %d liens."
+#: application/front/controller/admin/ManageTagController.php:105
+msgid "Tags separator must be a single character."
+msgstr "Un séparateur de tags doit contenir un seul caractère."
+
+#: application/front/controller/admin/ManageTagController.php:111
+msgid "These characters are reserved and can't be used as tags separator: "
+msgstr ""
+"Ces caractères sont réservés et ne peuvent être utilisés comme des "
+"séparateurs de tags : "
+
#: application/front/controller/admin/PasswordController.php:28
#: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:35
"Une erreur s'est produite lors de la sauvegarde de la configuration des "
"plugins : "
-#: application/front/controller/admin/ServerController.php:50
+#: application/front/controller/admin/ServerController.php:35
+msgid "Check disabled"
+msgstr "Vérification désactivée"
+
+#: application/front/controller/admin/ServerController.php:57
#: tmp/server.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28
msgid "Server administration"
msgstr "Administration serveur"
-#: application/front/controller/admin/ServerController.php:67
+#: application/front/controller/admin/ServerController.php:74
msgid "Thumbnails cache has been cleared."
msgstr "Le cache des miniatures a été vidé."
-#: application/front/controller/admin/ServerController.php:76
+#: application/front/controller/admin/ServerController.php:83
msgid "Shaarli's cache folder has been cleared!"
msgstr "Le dossier de cache de Shaarli a été vidé !"
msgid "Invalid visibility provided."
msgstr "Visibilité du lien non valide."
-#: application/front/controller/admin/ShaarePublishController.php:168
+#: application/front/controller/admin/ShaarePublishController.php:171
#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:171
msgid "Edit"
msgstr "Modifier"
-#: application/front/controller/admin/ShaarePublishController.php:171
+#: application/front/controller/admin/ShaarePublishController.php:174
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:28
msgid "Shaare"
msgstr "Shaare"
-#: application/front/controller/admin/ShaarePublishController.php:202
+#: application/front/controller/admin/ShaarePublishController.php:205
msgid "Note: "
msgstr "Note : "
msgid "Tools"
msgstr "Outils"
-#: application/front/controller/visitor/BookmarkListController.php:116
+#: application/front/controller/visitor/BookmarkListController.php:120
msgid "Search: "
msgstr "Recherche : "
msgid "Picture wall"
msgstr "Mur d'images"
-#: application/front/controller/visitor/TagCloudController.php:88
+#: application/front/controller/visitor/TagCloudController.php:90
msgid "Tag "
msgstr "Tag "
msgid "tag list"
msgstr "liste des tags"
+#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:47
+msgid "Change tags separator"
+msgstr "Changer le séparateur de tags"
+
+#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:50
+msgid "Your current tag separator is"
+msgstr "Votre séparateur actuel est"
+
+#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:53
+msgid "New separator"
+msgstr "Nouveau séparateur"
+
+#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:58
+#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:355
+#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:121
+#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:139
+#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:199
+msgid "Save"
+msgstr "Enregistrer"
+
+#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:61
+msgid "Note that hashtags won't fully work with a non-whitespace separator."
+msgstr ""
+"Notez que les hashtags ne sont pas complètement fonctionnels avec un "
+"séparateur qui n'est pas un espace."
+
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29
msgid "title"
msgstr "titre"
msgid "None"
msgstr "Aucune"
-#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:355
-#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:121
-#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:139
-#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:199
-msgid "Save"
-msgstr "Enregistrer"
-
#: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26
msgid "1 RSS entry per :type"
msgid_plural ""
msgstr "sans tag"
#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:175
-#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:43
-#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:43
+#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41
+#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:41
msgid "Fold"
msgstr "Replier"
#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:89
#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:29
#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:89
-#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44
-#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:44
+#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42
+#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:42
msgid "Fold all"
msgstr "Replier tout"
msgstr "Rester connecté"
#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15
-#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:50
+#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48
#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:15
-#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:50
+#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:48
msgid "by the Shaarli community"
msgstr "par la communauté Shaarli"
msgid "Documentation"
msgstr "Documentation"
-#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:45
-#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:45
+#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:43
+#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:43
msgid "Expand"
msgstr "Déplier"
-#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:46
-#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:46
+#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44
+#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:44
msgid "Expand all"
msgstr "Déplier tout"
-#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:47
-#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:47
+#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:45
+#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:45
msgid "Are you sure you want to delete this link?"
msgstr "Êtes-vous sûr de vouloir supprimer ce lien ?"
-#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48
-#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:48
+#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:46
+#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:46
msgid "Are you sure you want to delete this tag?"
msgstr "Êtes-vous sûr de vouloir supprimer ce tag ?"
<div class="dailyAbout">
All links of one day<br>in a single page.<br>
- {if="$previousday"} <a href="{$base_path}/daily&day={$previousday}"><b><</b>Previous day</a>{else}<b><</b>Previous day{/if}
+ {if="$previousday"} <a href="{$base_path}/daily?day={$previousday}"><b><</b>Previous day</a>{else}<b><</b>Previous day{/if}
-
- {if="$nextday"}<a href="{$base_path}/daily&day={$nextday}">Next day<b>></b></a>{else}Next day<b>></b>{/if}
+ {if="$nextday"}<a href="{$base_path}/daily?day={$nextday}">Next day<b>></b></a>{else}Next day<b>></b>{/if}
<br>
{loop="$daily_about_plugin"}
{$link=$value}
<div class="dailyEntry">
<div class="dailyEntryPermalink">
- <a href="{$base_path}/?{$value.shorturl}">
+ <a href="{$base_path}/shaare/{$value.shorturl}">
<img src="{$asset_path}/img/squiggle.png#" width="25" height="26" title="permalink" alt="permalink">
</a>
</div>
{if="!$hide_timestamps || $is_logged_in"}
<div class="dailyEntryLinkdate">
- <a href="{$base_path}/?{$value.shorturl}">{function="strftime('%c', $link.timestamp)"}</a>
+ <a href="{$base_path}/shaare/{$value.shorturl}">{function="strftime('%c', $link.timestamp)"}</a>
</div>
{/if}
{if="$link.tags"}
{if="$link.title==''"}onload="document.linkform.lf_title.focus();"
{elseif="$link.description==''"}onload="document.linkform.lf_description.focus();"
{else}onload="document.linkform.lf_tags.focus();"{/if} >
+{$asyncLoadClass=$link_is_new && $async_metadata && empty($link.title) ? 'loading-input' : ''}
<div id="pageheader">
{include="page.header"}
<div id="shaarli_title"><a href="{$titleLink}">{$shaarlititle}</a></div>
{if="isset($link.id)"}
<input type="hidden" name="lf_id" value="{$link.id}">
{/if}
- <label for="lf_url"><i>URL</i></label><br><input type="text" name="lf_url" id="lf_url" value="{$link.url}" class="lf_input"><br>
- <label for="lf_title"><i>Title</i></label><br><input type="text" name="lf_title" id="lf_title" value="{$link.title}" class="lf_input"><br>
- <label for="lf_description"><i>Description</i></label><br><textarea name="lf_description" id="lf_description" rows="4" cols="25">{$link.description}</textarea><br>
- <label for="lf_tags"><i>Tags</i></label><br>
- <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" ><br>
+ <label for="lf_url"><i>URL</i></label><br><input type="text" name="lf_url" id="lf_url" value="{$link.url}" class="lf_input">
+ <label for="lf_title"><i>Title</i></label>
+ <div class="{$asyncLoadClass}">
+ <input type="text" name="lf_title" id="lf_title" value="{$link.title}" class="lf_input">
+ <div class="icon-container">
+ <i class="loader"></i>
+ </div>
+ </div>
+ <label for="lf_description"><i>Description</i></label>
+ <div class="{if="$retrieve_description"}{$asyncLoadClass}{/if}">
+ <textarea name="lf_description" id="lf_description" rows="4" cols="25">{$link.description}</textarea>
+ <div class="icon-container">
+ <i class="loader"></i>
+ </div>
+ </div>
+ <label for="lf_tags"><i>Tags</i></label>
+ <div class="{if="$retrieve_description"}{$asyncLoadClass}{/if}">
+ <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" >
+ <div class="icon-container">
+ <i class="loader"></i>
+ </div>
+ </div>
{if="$formatter==='markdown'"}
<div class="md_help">
</div>
</div>
{include="page.footer"}
-</body>
+{if="$link_is_new && $async_metadata"}<script src="{$asset_path}/js/metadata.min.js?v={$version_hash}#"></script>{/if}</body>
</html>
</ul>
{/if}
+{if="!empty($global_errors)"}
+ <ul class="errors">
+ {loop="$global_errors"}
+ <li>{$value}</li>
+ {/loop}
+ </ul>
+{/if}
+
+{if="!empty($global_warnings)"}
+ <ul class="warnings">
+ {loop="$global_warnings"}
+ <li>{$value}</li>
+ {/loop}
+ </ul>
+{/if}
+
+{if="!empty($global_successes)"}
+ <ul class="successes">
+ {loop="$global_successes"}
+ <li>{$value}</li>
+ {/loop}
+ </ul>
+{/if}
+
<div class="clear"></div>