mirror of
https://github.com/wallabag/wallabag.git
synced 2024-12-23 16:10:28 +00:00
Merge remote-tracking branch 'origin/master' into 2.5.0
This commit is contained in:
commit
4947ea6758
106 changed files with 2100 additions and 1461 deletions
12
.github/CONTRIBUTING.md
vendored
12
.github/CONTRIBUTING.md
vendored
|
@ -6,11 +6,15 @@
|
||||||
|
|
||||||
- Clone the repository
|
- Clone the repository
|
||||||
- Ensure your Docker daemon is running
|
- Ensure your Docker daemon is running
|
||||||
- Launch `docker-compose up`
|
- Copy `docker/php/env.example` to `docker/php/env` and customize
|
||||||
|
- Launch `docker-compose run --rm php composer install` to bootstrap php dependencies
|
||||||
|
- Launch `docker-compose run --rm php bin/console wallabag:install` to bootstrap your installation
|
||||||
|
- Launch `docker-compose run --rm php yarn install` to bootstrap dependencies for the frontend
|
||||||
|
- Launch `docker-compose run --rm php yarn build:dev` to build assets for the frontend
|
||||||
|
- Launch `docker-compose up -d` to start the stack
|
||||||
|
|
||||||
You'll then have:
|
You'll then have:
|
||||||
- a web server (nginx)
|
- a PHP daemon with standalone web server
|
||||||
- a PHP daemon (using FPM)
|
|
||||||
- a Redis database (to handle imports)
|
- a Redis database (to handle imports)
|
||||||
- a SQLite database to store articles
|
- a SQLite database to store articles
|
||||||
|
|
||||||
|
@ -20,7 +24,7 @@ If you want to test using an other database than SQLite, uncomment the `postgres
|
||||||
|
|
||||||
### Using your own PHP server
|
### Using your own PHP server
|
||||||
|
|
||||||
- Ensure you are running PHP > 7.1.
|
- Ensure you are running PHP >= 7.4.
|
||||||
- Clone the repository
|
- Clone the repository
|
||||||
- Launch `composer install`
|
- Launch `composer install`
|
||||||
- If you got some errors, fix them (they might be related to some missing PHP extension from your machine)
|
- If you got some errors, fix them (they might be related to some missing PHP extension from your machine)
|
||||||
|
|
7
.github/dependabot.yml
vendored
7
.github/dependabot.yml
vendored
|
@ -34,3 +34,10 @@ updates:
|
||||||
- dependency-name: nelmio/api-doc-bundle
|
- dependency-name: nelmio/api-doc-bundle
|
||||||
versions:
|
versions:
|
||||||
- "> 2.13.4"
|
- "> 2.13.4"
|
||||||
|
- package-ecosystem: github-actions
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: weekly
|
||||||
|
time: "04:00"
|
||||||
|
timezone: Europe/Paris
|
||||||
|
open-pull-requests-limit: 10
|
||||||
|
|
BIN
.github/images/screenshot.png
vendored
Normal file
BIN
.github/images/screenshot.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 837 KiB |
7
.github/workflows/assets.yml
vendored
7
.github/workflows/assets.yml
vendored
|
@ -7,6 +7,9 @@ on:
|
||||||
- master
|
- master
|
||||||
- 2.*
|
- 2.*
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
js:
|
js:
|
||||||
name: "Building assets"
|
name: "Building assets"
|
||||||
|
@ -14,10 +17,10 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout"
|
- name: "Checkout"
|
||||||
uses: "actions/checkout@v2"
|
uses: "actions/checkout@v3"
|
||||||
|
|
||||||
- name: "Install Node"
|
- name: "Install Node"
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: "12"
|
node-version: "12"
|
||||||
|
|
||||||
|
|
7
.github/workflows/coding-standards.yml
vendored
7
.github/workflows/coding-standards.yml
vendored
|
@ -7,6 +7,9 @@ on:
|
||||||
- master
|
- master
|
||||||
- 2.*
|
- 2.*
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
coding-standards:
|
coding-standards:
|
||||||
name: "CS Fixer & PHPStan"
|
name: "CS Fixer & PHPStan"
|
||||||
|
@ -14,14 +17,14 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout"
|
- name: "Checkout"
|
||||||
uses: "actions/checkout@v2"
|
uses: "actions/checkout@v3"
|
||||||
|
|
||||||
- name: "Install PHP"
|
- name: "Install PHP"
|
||||||
uses: "shivammathur/setup-php@v2"
|
uses: "shivammathur/setup-php@v2"
|
||||||
with:
|
with:
|
||||||
coverage: "none"
|
coverage: "none"
|
||||||
php-version: "7.4"
|
php-version: "7.4"
|
||||||
tools: cs2pr, pecl, composer:v2
|
tools: cs2pr, pecl, composer:2.2
|
||||||
extensions: pdo, pdo_mysql, pdo_sqlite, pdo_pgsql, curl, imagick, pgsql, gd, tidy
|
extensions: pdo, pdo_mysql, pdo_sqlite, pdo_pgsql, curl, imagick, pgsql, gd, tidy
|
||||||
ini-values: "date.timezone=Europe/Paris"
|
ini-values: "date.timezone=Europe/Paris"
|
||||||
env:
|
env:
|
||||||
|
|
8
.github/workflows/continuous-integration.yml
vendored
8
.github/workflows/continuous-integration.yml
vendored
|
@ -29,8 +29,6 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
php:
|
php:
|
||||||
- "7.2"
|
|
||||||
- "7.3"
|
|
||||||
- "7.4"
|
- "7.4"
|
||||||
- "8.0"
|
- "8.0"
|
||||||
- "8.1"
|
- "8.1"
|
||||||
|
@ -41,7 +39,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout"
|
- name: "Checkout"
|
||||||
uses: "actions/checkout@v2"
|
uses: "actions/checkout@v3"
|
||||||
with:
|
with:
|
||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
|
|
||||||
|
@ -50,7 +48,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
php-version: "${{ matrix.php }}"
|
php-version: "${{ matrix.php }}"
|
||||||
coverage: none
|
coverage: none
|
||||||
tools: pecl, composer:v2
|
tools: pecl, composer:2.2
|
||||||
extensions: json, pdo, pdo_mysql, pdo_sqlite, pdo_pgsql, curl, imagick, pgsql, gd, tidy
|
extensions: json, pdo, pdo_mysql, pdo_sqlite, pdo_pgsql, curl, imagick, pgsql, gd, tidy
|
||||||
ini-values: "date.timezone=Europe/Paris"
|
ini-values: "date.timezone=Europe/Paris"
|
||||||
|
|
||||||
|
@ -58,7 +56,7 @@ jobs:
|
||||||
if: "${{ matrix.database == 'mysql' }}"
|
if: "${{ matrix.database == 'mysql' }}"
|
||||||
run: |
|
run: |
|
||||||
sudo systemctl start mysql.service
|
sudo systemctl start mysql.service
|
||||||
sudo mysql -u root -proot -e "CREATE DATABASE wallabag_test"
|
sudo mysql -u root -proot -h 127.0.0.1 -e "CREATE DATABASE wallabag_test"
|
||||||
|
|
||||||
- name: "Setup PostgreSQL"
|
- name: "Setup PostgreSQL"
|
||||||
if: "${{ matrix.database == 'pgsql' }}"
|
if: "${{ matrix.database == 'pgsql' }}"
|
||||||
|
|
7
.github/workflows/translations.yml
vendored
7
.github/workflows/translations.yml
vendored
|
@ -7,6 +7,9 @@ on:
|
||||||
- master
|
- master
|
||||||
- 2.*
|
- 2.*
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
translations:
|
translations:
|
||||||
name: "Translations"
|
name: "Translations"
|
||||||
|
@ -19,14 +22,14 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout"
|
- name: "Checkout"
|
||||||
uses: "actions/checkout@v2"
|
uses: "actions/checkout@v3"
|
||||||
|
|
||||||
- name: "Install PHP"
|
- name: "Install PHP"
|
||||||
uses: "shivammathur/setup-php@v2"
|
uses: "shivammathur/setup-php@v2"
|
||||||
with:
|
with:
|
||||||
coverage: "none"
|
coverage: "none"
|
||||||
php-version: "${{ matrix.php }}"
|
php-version: "${{ matrix.php }}"
|
||||||
tools: pecl, composer:v2
|
tools: pecl, composer:2.2
|
||||||
extensions: pdo, pdo_mysql, pdo_sqlite, pdo_pgsql, curl, imagick, pgsql, gd, tidy
|
extensions: pdo, pdo_mysql, pdo_sqlite, pdo_pgsql, curl, imagick, pgsql, gd, tidy
|
||||||
ini-values: "date.timezone=Europe/Paris"
|
ini-values: "date.timezone=Europe/Paris"
|
||||||
env:
|
env:
|
||||||
|
|
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -15,6 +15,7 @@
|
||||||
!/bin/symfony_requirements
|
!/bin/symfony_requirements
|
||||||
.php_cs.cache
|
.php_cs.cache
|
||||||
.phpunit.result.cache
|
.phpunit.result.cache
|
||||||
|
phpunit.xml
|
||||||
|
|
||||||
# Parameters
|
# Parameters
|
||||||
/app/config/parameters.yml
|
/app/config/parameters.yml
|
||||||
|
@ -35,16 +36,15 @@ web/uploads/
|
||||||
/build
|
/build
|
||||||
/coverage
|
/coverage
|
||||||
|
|
||||||
|
# Development
|
||||||
|
docker/php/env
|
||||||
|
|
||||||
# Composer PHAR
|
# Composer PHAR
|
||||||
/composer.phar
|
/composer.phar
|
||||||
|
|
||||||
# Data for wallabag
|
# Data for wallabag
|
||||||
data/db/wallabag*.sqlite
|
data/db/wallabag*.sqlite
|
||||||
|
|
||||||
# Docker container logs and data
|
|
||||||
docker/logs/
|
|
||||||
docker/data/
|
|
||||||
|
|
||||||
# assets stuff
|
# assets stuff
|
||||||
node_modules/
|
node_modules/
|
||||||
bin
|
bin
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
wallabag is mainly developed by [Nicolas Lœuillet](https://github.com/nicosomb), [@j0k3r](https://github.com/j0k3r) and [@tcitworld](https://github.com/tcitworld) under the MIT License.
|
wallabag is mainly developed by [Nicolas Lœuillet](https://github.com/nicosomb), [@j0k3r](https://github.com/j0k3r), [@tcitworld](https://github.com/tcitworld) and [@Kdecherf](https://github.com/Kdecherf) under the MIT License.
|
||||||
|
|
||||||
Thank you [to others contributors](https://github.com/wallabag/wallabag/graphs/contributors).
|
Thank you [to others contributors](https://github.com/wallabag/wallabag/graphs/contributors).
|
||||||
|
|
|
@ -46,7 +46,7 @@ fixtures: ## Load fixtures into database
|
||||||
php bin/console doctrine:fixtures:load --no-interaction --env=test
|
php bin/console doctrine:fixtures:load --no-interaction --env=test
|
||||||
|
|
||||||
test: prepare fixtures ## Launch wallabag testsuite
|
test: prepare fixtures ## Launch wallabag testsuite
|
||||||
bin/simple-phpunit -v
|
XDEBUG_MODE=off bin/simple-phpunit -v
|
||||||
|
|
||||||
release: ## Create a package. Need a VERSION parameter (eg: `make release VERSION=master`).
|
release: ## Create a package. Need a VERSION parameter (eg: `make release VERSION=master`).
|
||||||
ifndef VERSION
|
ifndef VERSION
|
||||||
|
|
48
README.md
48
README.md
|
@ -1,20 +1,32 @@
|
||||||
<img src="https://raw.githubusercontent.com/wallabag/logo/master/_default/typo-horizontal/png/sm/logo-typo-horizontal-black-no-bg-no-border-sm.png" align="right" />
|
# wallabag
|
||||||
|
|
||||||
![CI](https://github.com/wallabag/wallabag/workflows/CI/badge.svg)
|
![CI](https://github.com/wallabag/wallabag/workflows/CI/badge.svg)
|
||||||
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/wallabag/wallabag/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/wallabag/wallabag/?branch=master)
|
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/wallabag/wallabag/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/wallabag/wallabag/?branch=master)
|
||||||
[![Gitter](https://badges.gitter.im/gitterHQ/gitter.svg)](https://gitter.im/wallabag/wallabag)
|
[![Gitter](https://badges.gitter.im/gitterHQ/gitter.svg)](https://gitter.im/wallabag/wallabag)
|
||||||
[![Donation Status](https://img.shields.io/liberapay/goal/wallabag.svg?logo=liberapay)](https://liberapay.com/wallabag/donate)
|
[![Donation Status](https://img.shields.io/liberapay/goal/wallabag.svg?logo=liberapay)](https://liberapay.com/wallabag/donate)
|
||||||
[![Translation status](https://hosted.weblate.org/widgets/wallabag/-/svg-badge.svg)](https://hosted.weblate.org/engage/wallabag/?utm_source=widget)
|
[![Translation status](https://hosted.weblate.org/widgets/wallabag/-/svg-badge.svg)](https://hosted.weblate.org/engage/wallabag/?utm_source=widget)
|
||||||
|
![License](https://img.shields.io/github/license/wallabag/wallabag)
|
||||||
|
|
||||||
# What is wallabag?
|
wallabag is a web application allowing you to save web pages for later reading.
|
||||||
wallabag is a self-hostable PHP application allowing you to not miss any content anymore.
|
Click, save and read it when you want. It extracts content so that you won't be distracted by pop-ups and cie.
|
||||||
Click, save and read it when you can. It extracts content so that you can read it when you have time.
|
|
||||||
|
|
||||||
More information on our website: [wallabag.org](https://wallabag.org).
|
You can install it on your own server, or you can create an account on [wallabag.it](https://wallabag.it).
|
||||||
|
|
||||||
If you do not have your own server, consider [the wallabag.it hosting solution](https://wallabag.it).
|
![wallabag](./.github/images/screenshot.png)
|
||||||
|
|
||||||
|
* Website: [wallabag.org](https://wallabag.org)
|
||||||
|
* Android app: [wallabag/android-app](https://github.com/wallabag/android-app)
|
||||||
|
* iOS app: [wallabag/ios-app](https://github.com/wallabag/ios-app)
|
||||||
|
* Browser extension: [wallabag/wallabagger](https://github.com/wallabag/wallabagger)
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
The documentation is available at https://doc.wallabag.org.
|
||||||
|
|
||||||
|
You can contribute to it through its dedicated repository, available here: https://github.com/wallabag/doc.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
# Install wallabag
|
|
||||||
Please read [the documentation to see the wallabag requirements](https://doc.wallabag.org/en/admin/installation/requirements.html).
|
Please read [the documentation to see the wallabag requirements](https://doc.wallabag.org/en/admin/installation/requirements.html).
|
||||||
|
|
||||||
Then you can install wallabag by executing the following commands:
|
Then you can install wallabag by executing the following commands:
|
||||||
|
@ -26,16 +38,24 @@ cd wallabag && make install
|
||||||
|
|
||||||
Now, [configure a virtual host](https://doc.wallabag.org/en/admin/installation/virtualhosts.html) to use your wallabag.
|
Now, [configure a virtual host](https://doc.wallabag.org/en/admin/installation/virtualhosts.html) to use your wallabag.
|
||||||
|
|
||||||
# Run on YunoHost
|
### Other methods
|
||||||
[![Install Wallabag with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=wallabag2)
|
|
||||||
|
|
||||||
Wallabag app for [YunoHost](https://yunohost.org). See [here](https://github.com/YunoHost-Apps/wallabag2_ynh)
|
Refer to the [installation documentation](https://doc.wallabag.org/en/admin/installation/installation.html) for other installation methods.
|
||||||
|
|
||||||
# Translate wallabag
|
## Translation
|
||||||
|
|
||||||
[wallabag](https://hosted.weblate.org/projects/wallabag/) is being translated using [Weblate](https://weblate.org/), a web tool designed to ease translating for both developers and translators. Feel free to help us [translate wallabag](https://hosted.weblate.org/projects/wallabag/)!
|
This project uses [Weblate](https://weblate.org/) for translation.
|
||||||
|
|
||||||
# License
|
Feel free to help us [translating wallabag](https://hosted.weblate.org/projects/wallabag/).
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
To learn more about developing wallabag, please refer to the [contribution guide](./.github/CONTRIBUTING.md).
|
||||||
|
|
||||||
|
Content extraction relies on [Graby](https://github.com/j0k3r/graby), [php-readability](https://github.com/j0k3r/php-readability) and [ftr-site-config](https://github.com/fivefilters/ftr-site-config).
|
||||||
|
|
||||||
|
## License
|
||||||
Copyright © 2013-current Nicolas Lœuillet <nicolas@loeuillet.org>
|
Copyright © 2013-current Nicolas Lœuillet <nicolas@loeuillet.org>
|
||||||
|
|
||||||
This work is free. You can redistribute it and/or modify it under the
|
This work is free. You can redistribute it and/or modify it under the
|
||||||
terms of the MIT License. See the COPYING file for more details.
|
terms of the MIT License. See the [COPYING.md](./COPYING.md) file for more details.
|
||||||
|
|
|
@ -38,7 +38,7 @@ be locally specified in `composer.lock`:
|
||||||
```json
|
```json
|
||||||
"config": {
|
"config": {
|
||||||
"platform": {
|
"platform": {
|
||||||
"php": "7.1.3",
|
"php": "7.4.29",
|
||||||
"ext-something": "4.0"
|
"ext-something": "4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,16 +6,6 @@ main {
|
||||||
#content {
|
#content {
|
||||||
padding: 0 0.5rem;
|
padding: 0 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul.row {
|
|
||||||
margin: 0.4rem 0 0;
|
|
||||||
padding: 0 0.75rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.data .card .card-body {
|
|
||||||
height: 19em;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin mixin-reading-time {
|
@mixin mixin-reading-time {
|
||||||
|
@ -37,6 +27,11 @@ main {
|
||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
|
.card-content {
|
||||||
|
padding-bottom: 12px;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.card-content .card-title,
|
.card-content .card-title,
|
||||||
.card-reveal .card-title {
|
.card-reveal .card-title {
|
||||||
line-height: 22.8px;
|
line-height: 22.8px;
|
||||||
|
@ -95,7 +90,7 @@ main {
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-action {
|
.card-action {
|
||||||
padding: 10px 5px 10px 15px;
|
padding: 10px 10px 10px 15px;
|
||||||
|
|
||||||
ul.links {
|
ul.links {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -112,8 +107,9 @@ main {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul.tools li a.tool {
|
.tool {
|
||||||
margin-right: 5px !important;
|
display: flex;
|
||||||
|
margin-right: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include mixin-reading-time;
|
@include mixin-reading-time;
|
||||||
|
@ -134,6 +130,12 @@ main {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-body {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
a.original:not(.waves-effect) {
|
a.original:not(.waves-effect) {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
@ -311,3 +313,23 @@ a.original:not(.waves-effect) {
|
||||||
.settings .div_tabs {
|
.settings .div_tabs {
|
||||||
padding-bottom: 15px;
|
padding-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.entries-row {
|
||||||
|
display: grid;
|
||||||
|
margin: 0.4rem 0 0;
|
||||||
|
padding: 0 0.75rem;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry-card {
|
||||||
|
display: flex;
|
||||||
|
margin: 0;
|
||||||
|
height: 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.tools {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* ========================================================================== */
|
* ========================================================================== */
|
||||||
|
|
||||||
.mass-buttons {
|
.mass-buttons {
|
||||||
margin: 5px;
|
margin: 10px 5px 10px 20px;
|
||||||
|
|
||||||
#selectAll {
|
#selectAll {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -17,12 +17,13 @@
|
||||||
|
|
||||||
button {
|
button {
|
||||||
i {
|
i {
|
||||||
font-size: 12px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
height: 24px;
|
height: 24px;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
padding: 0 0.5rem;
|
padding: 0 0.5rem;
|
||||||
|
margin-right: 0.75rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,8 +39,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.entries {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
.collection {
|
.collection {
|
||||||
margin: 15px 15px 0;
|
margin: 5px 15px 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
.collection-item {
|
.collection-item {
|
||||||
padding: 7px;
|
padding: 7px;
|
||||||
|
|
|
@ -2,6 +2,12 @@
|
||||||
Media queries
|
Media queries
|
||||||
========================================================================== */
|
========================================================================== */
|
||||||
|
|
||||||
|
@media only screen and (min-width: 450px) {
|
||||||
|
.entries-row {
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media only screen and (min-width: 992px) {
|
@media only screen and (min-width: 992px) {
|
||||||
nav,
|
nav,
|
||||||
body:not(.entry):not(.login) main,
|
body:not(.entry):not(.login) main,
|
||||||
|
@ -180,15 +186,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 310px),
|
|
||||||
screen and (min-width: 601px) and (max-width: 660px),
|
|
||||||
screen and (min-width: 993px) and (max-width: 1050px),
|
|
||||||
screen and (min-width: 1201px) and (max-width: 1250px) {
|
|
||||||
.card .card-action .reading-time .card-created-at {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only print {
|
@media only print {
|
||||||
body {
|
body {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
|
@ -41,6 +41,18 @@ homepage:
|
||||||
fos_user:
|
fos_user:
|
||||||
resource: "@FOSUserBundle/Resources/config/routing/all.xml"
|
resource: "@FOSUserBundle/Resources/config/routing/all.xml"
|
||||||
|
|
||||||
|
fos_user_security_login:
|
||||||
|
path: /login
|
||||||
|
defaults:
|
||||||
|
_controller: Wallabag\UserBundle\Controller\SecurityController::loginAction
|
||||||
|
methods: [GET, POST]
|
||||||
|
|
||||||
|
fos_user_registration_register:
|
||||||
|
path: /register
|
||||||
|
defaults:
|
||||||
|
_controller: Wallabag\UserBundle\Controller\RegistrationController::registerAction
|
||||||
|
methods: [GET, POST]
|
||||||
|
|
||||||
fos_oauth_server_token:
|
fos_oauth_server_token:
|
||||||
resource: "@FOSOAuthServerBundle/Resources/config/routing/token.xml"
|
resource: "@FOSOAuthServerBundle/Resources/config/routing/token.xml"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
parameters:
|
parameters:
|
||||||
test_database_driver: pdo_mysql
|
test_database_driver: pdo_mysql
|
||||||
test_database_host: localhost
|
test_database_host: 127.0.0.1
|
||||||
test_database_port: 3306
|
test_database_port: 3306
|
||||||
test_database_name: wallabag_test
|
test_database_name: wallabag_test
|
||||||
test_database_user: root
|
test_database_user: root
|
||||||
|
|
|
@ -22,6 +22,7 @@ wallabag_core:
|
||||||
uk: 'Українська'
|
uk: 'Українська'
|
||||||
hr: 'Hrvatski'
|
hr: 'Hrvatski'
|
||||||
cs: 'Čeština'
|
cs: 'Čeština'
|
||||||
|
el: 'Ελληνικά'
|
||||||
items_on_page: 12
|
items_on_page: 12
|
||||||
theme: material
|
theme: material
|
||||||
language: '%locale%'
|
language: '%locale%'
|
||||||
|
|
|
@ -33,13 +33,15 @@
|
||||||
"issues": "https://github.com/wallabag/wallabag/issues"
|
"issues": "https://github.com/wallabag/wallabag/issues"
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.2.5",
|
"php": ">=7.4",
|
||||||
|
"composer": "< 2.3",
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-curl": "*",
|
"ext-curl": "*",
|
||||||
"ext-dom": "*",
|
"ext-dom": "*",
|
||||||
"ext-gd": "*",
|
"ext-gd": "*",
|
||||||
"ext-hash": "*",
|
"ext-hash": "*",
|
||||||
"ext-iconv": "*",
|
"ext-iconv": "*",
|
||||||
|
"ext-intl": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-mbstring": "*",
|
"ext-mbstring": "*",
|
||||||
"ext-pcre": "*",
|
"ext-pcre": "*",
|
||||||
|
@ -95,7 +97,7 @@
|
||||||
"tecnickcom/tcpdf": "^6.3.0",
|
"tecnickcom/tcpdf": "^6.3.0",
|
||||||
"twig/extensions": "^1.5",
|
"twig/extensions": "^1.5",
|
||||||
"wallabag/php-mobi": "~1.0",
|
"wallabag/php-mobi": "~1.0",
|
||||||
"wallabag/phpepub": "^4.0.7.2",
|
"wallabag/phpepub": "^4.0.10",
|
||||||
"willdurand/hateoas-bundle": "~2.1"
|
"willdurand/hateoas-bundle": "~2.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
@ -162,7 +164,7 @@
|
||||||
"config": {
|
"config": {
|
||||||
"bin-dir": "bin",
|
"bin-dir": "bin",
|
||||||
"platform": {
|
"platform": {
|
||||||
"php": "7.2.5"
|
"php": "7.4.29"
|
||||||
},
|
},
|
||||||
"sort-packages": true,
|
"sort-packages": true,
|
||||||
"allow-plugins": {
|
"allow-plugins": {
|
||||||
|
|
1186
composer.lock
generated
1186
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,52 +1,64 @@
|
||||||
version: '2'
|
version: '3.8'
|
||||||
services:
|
services:
|
||||||
nginx:
|
|
||||||
image: nginx:alpine
|
|
||||||
ports:
|
|
||||||
- "8000:80"
|
|
||||||
volumes:
|
|
||||||
- ./docker/nginx/nginx.conf:/nginx.conf
|
|
||||||
- ./docker/logs/nginx:/var/log/nginx
|
|
||||||
- .:/var/www/html
|
|
||||||
links:
|
|
||||||
- php:php
|
|
||||||
command: nginx -c /nginx.conf
|
|
||||||
|
|
||||||
php:
|
php:
|
||||||
build:
|
build:
|
||||||
context: docker/php
|
context: docker/php
|
||||||
args:
|
# Use target 'rootless' if you run rootless Docker
|
||||||
# Set here your timezone using one of this: https://php.net/manual/en/timezones.php
|
target: default
|
||||||
timezone: 'Europe/Monaco'
|
|
||||||
ports:
|
|
||||||
- "9000:9000"
|
|
||||||
volumes:
|
volumes:
|
||||||
- .:/var/www/html
|
- .:/var/www/html
|
||||||
#links:
|
# Volumes for data-related folders
|
||||||
# - "postgres:rdbms"
|
- assets:/var/www/html/web/assets
|
||||||
# - "mariadb:rdbms"
|
- data:/var/www/html/data
|
||||||
|
- cache:/var/www/.cache
|
||||||
|
# Uncomment the following volume if you run rootless Docker
|
||||||
|
# A limitation blocks permissions on root docker, see
|
||||||
|
# https://github.com/moby/moby/issues/40881
|
||||||
|
# - type: tmpfs
|
||||||
|
# target: /var/www/html/var/cache
|
||||||
|
# Override third-party libraries for dev
|
||||||
|
# - ../graby-site-config:/var/www/html/vendor/j0k3r/graby-site-config
|
||||||
|
# - ../php-readability:/var/www/html/vendor/j0k3r/php-readability
|
||||||
|
# - ../graby:/var/www/html/vendor/j0k3r/graby
|
||||||
|
# - ../HTMLawed:/var/www/html/vendor/fossar/htmlawed
|
||||||
|
# - ../PHPePub:/var/www/html/vendor/wallabag/phpepub
|
||||||
|
# - ../guzzle-site-authenticator:/var/www/html/vendor/bdunogier/guzzle-site-authenticator
|
||||||
env_file:
|
env_file:
|
||||||
|
# Copy docker/php/env.example to docker/php/env and customize
|
||||||
- ./docker/php/env
|
- ./docker/php/env
|
||||||
# Comment non-used DBMS lines
|
# Uncomment the database engine you want, it will use sqlite if both are commented
|
||||||
# If all DBMS are commented out, sqlite will be used as default
|
|
||||||
# - ./docker/postgres/env
|
|
||||||
# - ./docker/mariadb/env
|
# - ./docker/mariadb/env
|
||||||
|
# - ./docker/postgres/env
|
||||||
|
# Uncomment to enable Xdebug
|
||||||
|
# - ./docker/php/xdebug
|
||||||
|
ports:
|
||||||
|
- 8000:8000
|
||||||
|
# Uncomment to permit Xdebug remote session
|
||||||
|
# - 9000:9000
|
||||||
|
depends_on:
|
||||||
|
# - mariadb
|
||||||
|
# - postgres
|
||||||
|
- redis
|
||||||
|
|
||||||
# postgres:
|
# postgres:
|
||||||
# image: postgres:11-alpine
|
# image: postgres:11-alpine
|
||||||
# ports:
|
# volumes:
|
||||||
# - "5432:5432"
|
# - db-data:/var/lib/postgresql/data
|
||||||
# volumes:
|
# env_file:
|
||||||
# - ./docker/data/pgsql:/var/lib/postgresql/data
|
# - ./docker/postgres/env
|
||||||
# env_file:
|
# healthcheck:
|
||||||
# - ./docker/postgres/env
|
# test: ["CMD-SHELL", "pg_isready -q || exit 1"]
|
||||||
|
# interval: 10s
|
||||||
|
# timeout: 3s
|
||||||
|
# retries: 3
|
||||||
|
|
||||||
# mariadb:
|
# mariadb:
|
||||||
# image: mariadb:10
|
# image: mariadb:10
|
||||||
# ports:
|
# ports:
|
||||||
# - "3306:3306"
|
# - "3306:3306"
|
||||||
# volumes:
|
# volumes:
|
||||||
# - ./docker/data/mariadb:/var/lib/mysql
|
# - db-data:/var/lib/mysql
|
||||||
# env_file:
|
# env_file:
|
||||||
# - ./docker/mariadb/env
|
# - ./docker/mariadb/env
|
||||||
|
|
||||||
|
@ -56,6 +68,19 @@ services:
|
||||||
# - "15672:15672"
|
# - "15672:15672"
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: redis:4-alpine
|
image: redis:6-alpine
|
||||||
ports:
|
healthcheck:
|
||||||
- "6379:6379"
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 3
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
db-data:
|
||||||
|
driver: local
|
||||||
|
assets:
|
||||||
|
driver: local
|
||||||
|
data:
|
||||||
|
driver: local
|
||||||
|
cache:
|
||||||
|
driver: local
|
||||||
|
|
|
@ -2,9 +2,9 @@ MYSQL_ROOT_PASSWORD=wallaroot
|
||||||
MYSQL_USER=wallabag
|
MYSQL_USER=wallabag
|
||||||
MYSQL_PASSWORD=wallapass
|
MYSQL_PASSWORD=wallapass
|
||||||
MYSQL_DATABASE=wallabag
|
MYSQL_DATABASE=wallabag
|
||||||
SYMFONY__ENV__DATABASE_DRIVER=pdo_mysql
|
DATABASE_DRIVER=pdo_mysql
|
||||||
SYMFONY__ENV__DATABASE_HOST=rdbms
|
DATABASE_HOST=mysql
|
||||||
SYMFONY__ENV__DATABASE_PORT=3306
|
DATABASE_PORT=3306
|
||||||
SYMFONY__ENV__DATABASE_NAME=wallabag
|
DATABASE_NAME=wallabag
|
||||||
SYMFONY__ENV__DATABASE_USER=wallabag
|
DATABASE_USER=wallabag
|
||||||
SYMFONY__ENV__DATABASE_PASSWORD=wallapass
|
DATABASE_PASSWORD=wallapass
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
user nginx;
|
|
||||||
worker_processes 1;
|
|
||||||
pid /var/run/nginx.pid;
|
|
||||||
|
|
||||||
events {
|
|
||||||
worker_connections 2048;
|
|
||||||
multi_accept on;
|
|
||||||
use epoll;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
|
|
||||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
|
||||||
'$status $body_bytes_sent "$http_referer" '
|
|
||||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
|
||||||
|
|
||||||
access_log /var/log/nginx/access.log main;
|
|
||||||
|
|
||||||
server_tokens off;
|
|
||||||
sendfile on;
|
|
||||||
tcp_nopush on;
|
|
||||||
tcp_nodelay on;
|
|
||||||
keepalive_timeout 15;
|
|
||||||
types_hash_max_size 2048;
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
access_log off;
|
|
||||||
error_log off;
|
|
||||||
gzip on;
|
|
||||||
gzip_disable "msie6";
|
|
||||||
open_file_cache max=100;
|
|
||||||
|
|
||||||
|
|
||||||
upstream php-upstream {
|
|
||||||
server php:9000;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
#server_name domain.tld www.domain.tld;
|
|
||||||
root /var/www/html/web;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
# try to serve file directly, fallback to app.php
|
|
||||||
try_files $uri /app.php$is_args$args;
|
|
||||||
}
|
|
||||||
# DEV
|
|
||||||
# This rule should only be placed on your development environment
|
|
||||||
# In production, don't include this and don't deploy app_dev.php or config.php
|
|
||||||
location ~ ^/(app_dev|config)\.php(/|$) {
|
|
||||||
fastcgi_pass php-upstream;
|
|
||||||
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
|
||||||
include fastcgi_params;
|
|
||||||
# When you are using symlinks to link the document root to the
|
|
||||||
# current version of your application, you should pass the real
|
|
||||||
# application path instead of the path to the symlink to PHP
|
|
||||||
# FPM.
|
|
||||||
# Otherwise, PHP's OPcache may not properly detect changes to
|
|
||||||
# your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126
|
|
||||||
# for more information).
|
|
||||||
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
|
||||||
fastcgi_param DOCUMENT_ROOT $realpath_root;
|
|
||||||
}
|
|
||||||
# PROD
|
|
||||||
location ~ ^/app\.php(/|$) {
|
|
||||||
fastcgi_pass php-upstream;
|
|
||||||
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
|
||||||
include fastcgi_params;
|
|
||||||
# When you are using symlinks to link the document root to the
|
|
||||||
# current version of your application, you should pass the real
|
|
||||||
# application path instead of the path to the symlink to PHP
|
|
||||||
# FPM.
|
|
||||||
# Otherwise, PHP's OPcache may not properly detect changes to
|
|
||||||
# your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126
|
|
||||||
# for more information).
|
|
||||||
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
|
||||||
fastcgi_param DOCUMENT_ROOT $realpath_root;
|
|
||||||
# Prevents URIs that include the front controller. This will 404:
|
|
||||||
# http://domain.tld/app.php/some-path
|
|
||||||
# Remove the internal directive to allow URIs like this
|
|
||||||
internal;
|
|
||||||
}
|
|
||||||
|
|
||||||
error_log /var/log/nginx/project_error.log;
|
|
||||||
access_log /var/log/nginx/project_access.log;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
daemon off;
|
|
|
@ -1,8 +1,19 @@
|
||||||
FROM php:7.2-fpm
|
FROM php:7.4-fpm AS rootless
|
||||||
|
|
||||||
# Default timezone. To change it, use the argument in the docker-compose.yml file
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
ARG timezone='Europe/Paris'
|
ARG NODE_VERSION=14
|
||||||
ARG memorylimit='512M'
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
gnupg \
|
||||||
|
lsb-release \
|
||||||
|
openssl \
|
||||||
|
software-properties-common
|
||||||
|
|
||||||
|
RUN curl 'https://deb.nodesource.com/gpgkey/nodesource.gpg.key' | apt-key add - \
|
||||||
|
&& echo "deb https://deb.nodesource.com/node_${NODE_VERSION}.x $(lsb_release -cs) main" > /etc/apt/sources.list.d/nodesource.list
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
libmcrypt-dev \
|
libmcrypt-dev \
|
||||||
|
@ -11,30 +22,77 @@ RUN apt-get update && apt-get install -y \
|
||||||
libxml2-dev \
|
libxml2-dev \
|
||||||
libpng-dev \
|
libpng-dev \
|
||||||
libjpeg-dev \
|
libjpeg-dev \
|
||||||
|
libwebp-dev \
|
||||||
libsqlite3-dev \
|
libsqlite3-dev \
|
||||||
imagemagick \
|
imagemagick \
|
||||||
libmagickwand-dev \
|
libmagickwand-dev \
|
||||||
libtidy-dev \
|
libtidy-dev \
|
||||||
git
|
libonig-dev \
|
||||||
RUN docker-php-ext-install \
|
libzip-dev \
|
||||||
iconv \
|
libfreetype6-dev \
|
||||||
mbstring \
|
zlib1g-dev \
|
||||||
|
git \
|
||||||
|
build-essential \
|
||||||
|
nodejs
|
||||||
|
RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp
|
||||||
|
RUN docker-php-ext-install -j "$(nproc)" \
|
||||||
|
bcmath \
|
||||||
gd \
|
gd \
|
||||||
|
gettext \
|
||||||
|
iconv \
|
||||||
intl \
|
intl \
|
||||||
|
mbstring \
|
||||||
|
opcache \
|
||||||
pdo \
|
pdo \
|
||||||
pdo_mysql \
|
pdo_mysql \
|
||||||
pdo_pgsql \
|
pdo_pgsql \
|
||||||
pdo_sqlite \
|
pdo_sqlite \
|
||||||
sockets \
|
sockets \
|
||||||
tidy \
|
tidy \
|
||||||
bcmath \
|
|
||||||
zip
|
zip
|
||||||
|
|
||||||
RUN printf "\n" | pecl install imagick && docker-php-ext-enable imagick
|
RUN pecl install redis; \
|
||||||
|
pecl install imagick; \
|
||||||
|
pecl install xdebug; \
|
||||||
|
docker-php-ext-enable \
|
||||||
|
redis \
|
||||||
|
imagick \
|
||||||
|
xdebug \
|
||||||
|
;
|
||||||
|
|
||||||
RUN echo "date.timezone="$timezone > /usr/local/etc/php/conf.d/date_timezone.ini
|
RUN npm install -g yarn
|
||||||
RUN echo "memory_limit ="$memorylimit > /usr/local/etc/php/conf.d/memory_limit.ini
|
|
||||||
|
|
||||||
RUN usermod -u 1000 www-data
|
RUN curl -L -o /usr/local/bin/envsubst https://github.com/a8m/envsubst/releases/download/v1.1.0/envsubst-`uname -s`-`uname -m`; \
|
||||||
|
chmod +x /usr/local/bin/envsubst
|
||||||
|
|
||||||
CMD ["php-fpm"]
|
COPY --from=composer:2.2.12 /usr/bin/composer /usr/local/bin/composer
|
||||||
|
|
||||||
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
COPY config/ /opt/wallabag/config/
|
||||||
|
|
||||||
|
RUN mkdir -p \
|
||||||
|
/var/www/html/app/config/ \
|
||||||
|
/var/www/html/var/cache \
|
||||||
|
/var/www/html/web/assets \
|
||||||
|
/var/www/html/data \
|
||||||
|
/var/www/html/data/db \
|
||||||
|
/var/www/.cache
|
||||||
|
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
|
CMD ["php", "bin/console", "--env=dev", "server:run", "0.0.0.0:8000"]
|
||||||
|
|
||||||
|
FROM rootless AS default
|
||||||
|
|
||||||
|
ARG USER_UID=1000
|
||||||
|
ARG USER_GID=1000
|
||||||
|
|
||||||
|
RUN groupmod -g 1000 www-data ; \
|
||||||
|
usermod -u ${USER_UID} -g www-data www-data ; \
|
||||||
|
touch /usr/local/etc/php/conf.d/wallabag-php.ini \
|
||||||
|
/var/www/.yarnrc ; \
|
||||||
|
chown -R www-data: /var/www/html \
|
||||||
|
/usr/local/etc/php/conf.d/wallabag-php.ini \
|
||||||
|
/var/www/.cache \
|
||||||
|
/var/www/.yarnrc
|
||||||
|
|
||||||
|
USER www-data
|
||||||
|
|
62
docker/php/config/parameters.yml
Normal file
62
docker/php/config/parameters.yml
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
parameters:
|
||||||
|
database_driver: ${DATABASE_DRIVER:-pdo_sqlite}
|
||||||
|
database_driver_class: ${DATABASE_DRIVER_CLASS:-~}
|
||||||
|
database_host: ${DATABASE_HOST:-127.0.0.1}
|
||||||
|
database_port: ${DATABASE_PORT:-~}
|
||||||
|
database_name: ${DATABASE_NAME:-symfony}
|
||||||
|
database_user: ${DATABASE_USER:-root}
|
||||||
|
database_password: ${DATABASE_PASSWORD:-~}
|
||||||
|
database_path: ${DATABASE_PATH:-"%kernel.root_dir%/data/db/wallabag.sqlite"}
|
||||||
|
database_table_prefix: wallabag_
|
||||||
|
database_socket: null
|
||||||
|
database_charset: ${DATABASE_CHARSET:-utf8}
|
||||||
|
|
||||||
|
domain_name: ${DOMAIN_NAME:-https://www.example.com}
|
||||||
|
server_name: ${SERVER_NAME:-"Your wallabag instance"}
|
||||||
|
|
||||||
|
mailer_transport: ${MAILER_TRANSPORT:-smtp}
|
||||||
|
mailer_user: ${MAILER_USER:-~}
|
||||||
|
mailer_password: ${MAILER_PASSWORD:-~}
|
||||||
|
mailer_host: ${MAILER_HOST:-127.0.0.1}
|
||||||
|
mailer_port: ${MAILER_PORT:-25}
|
||||||
|
mailer_encryption: ${MAILER_ENCRYPTION:-~}
|
||||||
|
mailer_auth_mode: ${MAILER_AUTH_MODE:-~}
|
||||||
|
|
||||||
|
locale: ${LOCALE:-en}
|
||||||
|
|
||||||
|
# A secret key that's used to generate certain security-related tokens
|
||||||
|
secret: ${SECRET:-~}
|
||||||
|
|
||||||
|
# two factor stuff
|
||||||
|
twofactor_auth: ${TWOFACTOR_AUTH:-true}
|
||||||
|
twofactor_sender: ${TWOFACTOR_SENDER:-no-reply@wallabag.org}
|
||||||
|
|
||||||
|
# fosuser stuff
|
||||||
|
fosuser_registration: ${FOSUSER_REGISTRATION:-true}
|
||||||
|
fosuser_confirmation: ${FOSUSER_CONFIRMATION:-true}
|
||||||
|
|
||||||
|
fos_oauth_server_access_token_lifetime: 3600
|
||||||
|
fos_oauth_server_refresh_token_lifetime: 1209600
|
||||||
|
|
||||||
|
from_email: ${FROM_EMAIL:-wallabag@example.com}
|
||||||
|
|
||||||
|
rss_limit: 50
|
||||||
|
|
||||||
|
# RabbitMQ processing
|
||||||
|
rabbitmq_host: localhost
|
||||||
|
rabbitmq_port: 5672
|
||||||
|
rabbitmq_user: guest
|
||||||
|
rabbitmq_password: guest
|
||||||
|
rabbitmq_prefetch_count: 10
|
||||||
|
|
||||||
|
# Redis processing
|
||||||
|
redis_scheme: ${REDIS_SCHEME:-tcp}
|
||||||
|
redis_host: ${REDIS_HOST:-redis}
|
||||||
|
redis_port: ${REDIS_PORT:-6379}
|
||||||
|
redis_path: ${REDIS_PATH:-~}
|
||||||
|
redis_password: ${REDIS_PASSWORD:-~}
|
||||||
|
|
||||||
|
# Sentry
|
||||||
|
sentry_dsn: ${SENTRY_DSN:-~}
|
||||||
|
|
||||||
|
session_handler: ${SESSION_HANDLER:-session.handler.native_file}
|
10
docker/php/config/wallabag-php.ini
Normal file
10
docker/php/config/wallabag-php.ini
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
memory_limit = ${PHP_MEMORY_LIMIT:-512M}
|
||||||
|
|
||||||
|
max_execution_time = ${PHP_MAX_EXECUTION_TIME:-60}
|
||||||
|
|
||||||
|
date.time = ${PHP_TIMEZONE:-Europe/Paris}
|
||||||
|
|
||||||
|
session.save_handler = ${PHP_SESSION_HANDLER:-files}
|
||||||
|
session.save_path = "${PHP_SESSION_SAVE_PATH:-}"
|
||||||
|
|
||||||
|
upload_max_filesize = 10M
|
6
docker/php/entrypoint.sh
Executable file
6
docker/php/entrypoint.sh
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
envsubst < /opt/wallabag/config/wallabag-php.ini > /usr/local/etc/php/conf.d/wallabag-php.ini
|
||||||
|
envsubst < /opt/wallabag/config/parameters.yml > /var/www/html/app/config/parameters.yml
|
||||||
|
|
||||||
|
exec "$@"
|
|
@ -1,6 +0,0 @@
|
||||||
SYMFONY__ENV__DATABASE_DRIVER=pdo_sqlite
|
|
||||||
SYMFONY__ENV__DATABASE_HOST=127.0.0.1
|
|
||||||
SYMFONY__ENV__DATABASE_PORT=~
|
|
||||||
SYMFONY__ENV__DATABASE_NAME=symfony
|
|
||||||
SYMFONY__ENV__DATABASE_USER=root
|
|
||||||
SYMFONY__ENV__DATABASE_PASSWORD=~
|
|
13
docker/php/env.example
Normal file
13
docker/php/env.example
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
DATABASE_DRIVER=pdo_sqlite
|
||||||
|
DATABASE_HOST=127.0.0.1
|
||||||
|
DATABASE_PORT=~
|
||||||
|
DATABASE_NAME=symfony
|
||||||
|
DATABASE_USER=root
|
||||||
|
DATABASE_PASSWORD=~
|
||||||
|
DATABASE_PATH="%kernel.project_dir%/data/db/wallabag.sqlite"
|
||||||
|
DOMAIN_NAME=http://localhost:8000
|
||||||
|
SECRET=ch4n63m31fy0uc4n
|
||||||
|
PHP_SESSION_SAVE_PATH=tcp://redis:6379?database=2
|
||||||
|
PHP_SESSION_HANDLER=redis
|
||||||
|
SESSION_HANDLER=~
|
||||||
|
TRUSTED_PROXIES=0.0.0.0/0
|
2
docker/php/xdebug
Normal file
2
docker/php/xdebug
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
XDEBUG_MODE=debug
|
||||||
|
XDEBUG_TRIGGER=yes
|
|
@ -1,9 +1,10 @@
|
||||||
POSTGRES_USER=wallabag
|
POSTGRES_USER=wallabag
|
||||||
POSTGRES_PASSWORD=wallapass
|
POSTGRES_PASSWORD=wallapass
|
||||||
POSTGRES_DB=wallabag
|
POSTGRES_DB=wallabag
|
||||||
SYMFONY__ENV__DATABASE_HOST=rdbms
|
DATABASE_HOST=postgres
|
||||||
SYMFONY__ENV__DATABASE_PORT=5432
|
DATABASE_PORT=5432
|
||||||
SYMFONY__ENV__DATABASE_NAME=wallabag
|
DATABASE_NAME=wallabag
|
||||||
SYMFONY__ENV__DATABASE_USER=wallabag
|
DATABASE_USER=wallabag
|
||||||
SYMFONY__ENV__DATABASE_PASSWORD=wallapass
|
DATABASE_PASSWORD=wallapass
|
||||||
SYMFONY__ENV__DATABASE_DRIVER=pdo_pgsql
|
DATABASE_DRIVER=pdo_pgsql
|
||||||
|
DATABASE_PATH=null
|
||||||
|
|
40
package.json
40
package.json
|
@ -36,48 +36,48 @@
|
||||||
"url": "https://github.com/wallabag/wallabag/issues"
|
"url": "https://github.com/wallabag/wallabag/issues"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.17.5",
|
"@babel/core": "^7.17.10",
|
||||||
"@babel/eslint-parser": "^7.17.0",
|
"@babel/eslint-parser": "^7.17.0",
|
||||||
"@babel/preset-env": "^7.16.11",
|
"@babel/preset-env": "^7.17.10",
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.7",
|
||||||
"babel-loader": "^8.2.3",
|
"babel-loader": "^8.2.5",
|
||||||
"css-loader": "^6.6.0",
|
"css-loader": "^6.7.1",
|
||||||
"eslint": "^8.10.0",
|
"eslint": "^8.15.0",
|
||||||
"eslint-config-airbnb-base": "^15.0.0",
|
"eslint-config-airbnb-base": "^15.0.0",
|
||||||
"eslint-plugin-import": "^2.25.4",
|
"eslint-plugin-import": "^2.26.0",
|
||||||
"eslint-webpack-plugin": "^3.1.1",
|
"eslint-webpack-plugin": "^3.1.1",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"lato-font": "^3.0.0",
|
"lato-font": "^3.0.0",
|
||||||
"mini-css-extract-plugin": "^2.5.3",
|
"mini-css-extract-plugin": "^2.6.0",
|
||||||
"node-sass": "^7.0.1",
|
"node-sass": "^7.0.1",
|
||||||
"postcss": "^8.4.7",
|
"postcss": "^8.4.13",
|
||||||
"postcss-loader": "^6.2.1",
|
"postcss-loader": "^6.2.1",
|
||||||
"postcss-scss": "^4.0.3",
|
"postcss-scss": "^4.0.4",
|
||||||
"sass": "^1.49.9",
|
"sass": "^1.51.0",
|
||||||
"sass-loader": "^12.6.0",
|
"sass-loader": "^12.6.0",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
"stylelint": "^14.5.3",
|
"stylelint": "^14.8.2",
|
||||||
"stylelint-config-standard": "^25.0.0",
|
"stylelint-config-standard": "^25.0.0",
|
||||||
"stylelint-scss": "^4.1.0",
|
"stylelint-scss": "^4.2.0",
|
||||||
"stylelint-webpack-plugin": "^3.1.1",
|
"stylelint-webpack-plugin": "^3.2.0",
|
||||||
"terser-webpack-plugin": "^5.3.1",
|
"terser-webpack-plugin": "^5.3.1",
|
||||||
"url-loader": "^4.1.1",
|
"url-loader": "^4.1.1",
|
||||||
"webpack": "^5.69.1",
|
"webpack": "^5.72.0",
|
||||||
"webpack-cli": "^4.9.2",
|
"webpack-cli": "^4.9.2",
|
||||||
"webpack-dev-server": "^4.7.4",
|
"webpack-dev-server": "^4.9.0",
|
||||||
"webpack-manifest-plugin": "^4.1.1",
|
"webpack-manifest-plugin": "^5.0.0",
|
||||||
"webpack-merge": "^5.7.3"
|
"webpack-merge": "^5.7.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"annotator": "wallabag/annotator#master",
|
"annotator": "wallabag/annotator#master",
|
||||||
"clipboard": "^2.0.10",
|
"clipboard": "^2.0.11",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
"highlight.js": "^11.4.0",
|
"highlight.js": "^11.5.1",
|
||||||
"icomoon-free-npm": "^0.0.0",
|
"icomoon-free-npm": "^0.0.0",
|
||||||
"jquery": "^3.6.0",
|
"jquery": "^3.6.0",
|
||||||
"jquery.cookie": "^1.4.1",
|
"jquery.cookie": "^1.4.1",
|
||||||
"jr-qrcode": "^1.0.7",
|
"jr-qrcode": "^1.0.7",
|
||||||
"material-design-icons-iconfont": "^6.4.2",
|
"material-design-icons-iconfont": "^6.7.0",
|
||||||
"materialize-css": "^0.98.1",
|
"materialize-css": "^0.98.1",
|
||||||
"mathjax": "^3.1.2",
|
"mathjax": "^3.1.2",
|
||||||
"mousetrap": "^1.6.0",
|
"mousetrap": "^1.6.0",
|
||||||
|
|
32
src/Wallabag/ApiBundle/Controller/ConfigRestController.php
Normal file
32
src/Wallabag/ApiBundle/Controller/ConfigRestController.php
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Wallabag\ApiBundle\Controller;
|
||||||
|
|
||||||
|
use JMS\Serializer\SerializationContext;
|
||||||
|
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
|
||||||
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
|
|
||||||
|
class ConfigRestController extends WallabagRestController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Retrieve configuration for current user.
|
||||||
|
*
|
||||||
|
* @ApiDoc()
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function getConfigAction()
|
||||||
|
{
|
||||||
|
$this->validateAuthentication();
|
||||||
|
|
||||||
|
$json = $this->get('jms_serializer')->serialize(
|
||||||
|
$this->getUser()->getConfig(),
|
||||||
|
'json',
|
||||||
|
SerializationContext::create()->setGroups(['config_api'])
|
||||||
|
);
|
||||||
|
|
||||||
|
return (new JsonResponse())
|
||||||
|
->setJson($json)
|
||||||
|
->setStatusCode(JsonResponse::HTTP_OK);
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,3 +32,8 @@ user:
|
||||||
type: rest
|
type: rest
|
||||||
resource: "WallabagApiBundle:UserRest"
|
resource: "WallabagApiBundle:UserRest"
|
||||||
name_prefix: api_
|
name_prefix: api_
|
||||||
|
|
||||||
|
config:
|
||||||
|
type: rest
|
||||||
|
resource: "WallabagApiBundle:ConfigRest"
|
||||||
|
name_prefix: api_
|
||||||
|
|
|
@ -41,7 +41,7 @@ class TagAllCommand extends ContainerAwareCommand
|
||||||
|
|
||||||
$entries = $tagger->tagAllForUser($user);
|
$entries = $tagger->tagAllForUser($user);
|
||||||
|
|
||||||
$io->text('Persist entries... ');
|
$io->text('Persist ' . \count($entries) . ' entries... ');
|
||||||
|
|
||||||
$em = $this->getDoctrine()->getManager();
|
$em = $this->getDoctrine()->getManager();
|
||||||
foreach ($entries as $entry) {
|
foreach ($entries as $entry) {
|
||||||
|
|
|
@ -43,6 +43,16 @@ class ConfigController extends Controller
|
||||||
$configForm->handleRequest($request);
|
$configForm->handleRequest($request);
|
||||||
|
|
||||||
if ($configForm->isSubmitted() && $configForm->isValid()) {
|
if ($configForm->isSubmitted() && $configForm->isValid()) {
|
||||||
|
// force theme to material to avoid using baggy
|
||||||
|
if ('baggy' === $config->getTheme()) {
|
||||||
|
$config->setTheme('material');
|
||||||
|
|
||||||
|
$this->addFlash(
|
||||||
|
'notice',
|
||||||
|
'Baggy is deprecated, forced to Material theme.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$em->persist($config);
|
$em->persist($config);
|
||||||
$em->flush();
|
$em->flush();
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,9 @@ use Pagerfanta\Exception\OutOfRangeCurrentPageException;
|
||||||
use Pagerfanta\Pagerfanta;
|
use Pagerfanta\Pagerfanta;
|
||||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||||
use Wallabag\CoreBundle\Entity\Tag;
|
use Wallabag\CoreBundle\Entity\Tag;
|
||||||
|
@ -88,8 +90,19 @@ class FeedController extends Controller
|
||||||
*
|
*
|
||||||
* @return \Symfony\Component\HttpFoundation\Response
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
*/
|
*/
|
||||||
public function showTagsFeedAction(User $user, Tag $tag, $page)
|
public function showTagsFeedAction(Request $request, User $user, Tag $tag, $page)
|
||||||
{
|
{
|
||||||
|
$sort = $request->query->get('sort', 'created');
|
||||||
|
|
||||||
|
$sorts = [
|
||||||
|
'created' => 'createdAt',
|
||||||
|
'updated' => 'updatedAt',
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!isset($sorts[$sort])) {
|
||||||
|
throw new BadRequestHttpException(sprintf('Sort "%s" is not available.', $sort));
|
||||||
|
}
|
||||||
|
|
||||||
$url = $this->generateUrl(
|
$url = $this->generateUrl(
|
||||||
'tag_feed',
|
'tag_feed',
|
||||||
[
|
[
|
||||||
|
@ -102,7 +115,8 @@ class FeedController extends Controller
|
||||||
|
|
||||||
$entriesByTag = $this->get('wallabag_core.entry_repository')->findAllByTagId(
|
$entriesByTag = $this->get('wallabag_core.entry_repository')->findAllByTagId(
|
||||||
$user->getId(),
|
$user->getId(),
|
||||||
$tag->getId()
|
$tag->getId(),
|
||||||
|
$sorts[$sort]
|
||||||
);
|
);
|
||||||
|
|
||||||
$pagerAdapter = new ArrayAdapter($entriesByTag);
|
$pagerAdapter = new ArrayAdapter($entriesByTag);
|
||||||
|
@ -137,11 +151,28 @@ class FeedController extends Controller
|
||||||
'domainName' => $this->getParameter('domain_name'),
|
'domainName' => $this->getParameter('domain_name'),
|
||||||
'version' => $this->getParameter('wallabag_core.version'),
|
'version' => $this->getParameter('wallabag_core.version'),
|
||||||
'tag' => $tag->getSlug(),
|
'tag' => $tag->getSlug(),
|
||||||
|
'updated' => $this->prepareFeedUpdatedDate($entries, $sort),
|
||||||
],
|
],
|
||||||
new Response('', 200, ['Content-Type' => 'application/atom+xml'])
|
new Response('', 200, ['Content-Type' => 'application/atom+xml'])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function prepareFeedUpdatedDate(Pagerfanta $entries, $sort = 'created')
|
||||||
|
{
|
||||||
|
$currentPageResults = $entries->getCurrentPageResults();
|
||||||
|
|
||||||
|
if (isset($currentPageResults[0])) {
|
||||||
|
$firstEntry = $currentPageResults[0];
|
||||||
|
if ('created' === $sort) {
|
||||||
|
return $firstEntry->getCreatedAt();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $firstEntry->getUpdatedAt();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global method to retrieve entries depending on the given type
|
* Global method to retrieve entries depending on the given type
|
||||||
* It returns the response to be send.
|
* It returns the response to be send.
|
||||||
|
@ -202,6 +233,7 @@ class FeedController extends Controller
|
||||||
'user' => $user->getUsername(),
|
'user' => $user->getUsername(),
|
||||||
'domainName' => $this->getParameter('domain_name'),
|
'domainName' => $this->getParameter('domain_name'),
|
||||||
'version' => $this->getParameter('wallabag_core.version'),
|
'version' => $this->getParameter('wallabag_core.version'),
|
||||||
|
'updated' => $this->prepareFeedUpdatedDate($entries),
|
||||||
],
|
],
|
||||||
new Response('', 200, ['Content-Type' => 'application/atom+xml'])
|
new Response('', 200, ['Content-Type' => 'application/atom+xml'])
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Wallabag\CoreBundle\Controller;
|
namespace Wallabag\CoreBundle\Controller;
|
||||||
|
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
use Pagerfanta\Adapter\ArrayAdapter;
|
use Pagerfanta\Adapter\ArrayAdapter;
|
||||||
use Pagerfanta\Exception\OutOfRangeCurrentPageException;
|
use Pagerfanta\Exception\OutOfRangeCurrentPageException;
|
||||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||||
|
@ -190,4 +191,35 @@ class TagController extends Controller
|
||||||
|
|
||||||
return $this->redirect($redirectUrl);
|
return $this->redirect($redirectUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tag search results with the current search term.
|
||||||
|
*
|
||||||
|
* @Route("/tag/search/{filter}", name="tag_this_search")
|
||||||
|
*
|
||||||
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
|
*/
|
||||||
|
public function tagThisSearchAction($filter, Request $request)
|
||||||
|
{
|
||||||
|
$currentRoute = $request->query->has('currentRoute') ? $request->query->get('currentRoute') : '';
|
||||||
|
|
||||||
|
/** @var QueryBuilder $qb */
|
||||||
|
$qb = $this->get('wallabag_core.entry_repository')->getBuilderForSearchByUser($this->getUser()->getId(), $filter, $currentRoute);
|
||||||
|
$em = $this->getDoctrine()->getManager();
|
||||||
|
|
||||||
|
$entries = $qb->getQuery()->getResult();
|
||||||
|
|
||||||
|
foreach ($entries as $entry) {
|
||||||
|
$this->get('wallabag_core.tags_assigner')->assignTagsToEntry(
|
||||||
|
$entry,
|
||||||
|
$filter
|
||||||
|
);
|
||||||
|
|
||||||
|
$em->persist($entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
return $this->redirect($this->get('wallabag_core.helper.redirect')->to($request->headers->get('referer'), '', true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ class ConfigFixtures extends Fixture implements DependentFixtureInterface
|
||||||
$emptyConfig = new Config($this->getReference('empty-user'));
|
$emptyConfig = new Config($this->getReference('empty-user'));
|
||||||
$emptyConfig->setTheme('material');
|
$emptyConfig->setTheme('material');
|
||||||
$emptyConfig->setItemsPerPage(10);
|
$emptyConfig->setItemsPerPage(10);
|
||||||
$emptyConfig->setReadingSpeed(200);
|
$emptyConfig->setReadingSpeed(100);
|
||||||
$emptyConfig->setLanguage('en');
|
$emptyConfig->setLanguage('en');
|
||||||
$emptyConfig->setPocketConsumerKey(null);
|
$emptyConfig->setPocketConsumerKey(null);
|
||||||
$emptyConfig->setActionMarkAsRead(0);
|
$emptyConfig->setActionMarkAsRead(0);
|
||||||
|
|
|
@ -43,6 +43,20 @@ class TaggingRuleFixtures extends Fixture implements DependentFixtureInterface
|
||||||
|
|
||||||
$manager->persist($tr4);
|
$manager->persist($tr4);
|
||||||
|
|
||||||
|
$tr5 = new TaggingRule();
|
||||||
|
$tr5->setRule('readingTime <= 5');
|
||||||
|
$tr5->setTags(['shortread']);
|
||||||
|
$tr5->setConfig($this->getReference('empty-config'));
|
||||||
|
|
||||||
|
$manager->persist($tr5);
|
||||||
|
|
||||||
|
$tr6 = new TaggingRule();
|
||||||
|
$tr6->setRule('readingTime > 5');
|
||||||
|
$tr6->setTags(['longread']);
|
||||||
|
$tr6->setConfig($this->getReference('empty-config'));
|
||||||
|
|
||||||
|
$manager->persist($tr6);
|
||||||
|
|
||||||
$manager->flush();
|
$manager->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace Wallabag\CoreBundle\Entity;
|
||||||
|
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use JMS\Serializer\Annotation\Groups;
|
||||||
use Symfony\Component\Validator\Constraints as Assert;
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
use Wallabag\UserBundle\Entity\User;
|
use Wallabag\UserBundle\Entity\User;
|
||||||
|
|
||||||
|
@ -29,6 +30,8 @@ class Config
|
||||||
* @ORM\Column(name="id", type="integer")
|
* @ORM\Column(name="id", type="integer")
|
||||||
* @ORM\Id
|
* @ORM\Id
|
||||||
* @ORM\GeneratedValue(strategy="AUTO")
|
* @ORM\GeneratedValue(strategy="AUTO")
|
||||||
|
*
|
||||||
|
* @Groups({"config_api"})
|
||||||
*/
|
*/
|
||||||
private $id;
|
private $id;
|
||||||
|
|
||||||
|
@ -50,6 +53,8 @@ class Config
|
||||||
* maxMessage = "validator.item_per_page_too_high"
|
* maxMessage = "validator.item_per_page_too_high"
|
||||||
* )
|
* )
|
||||||
* @ORM\Column(name="items_per_page", type="integer", nullable=false)
|
* @ORM\Column(name="items_per_page", type="integer", nullable=false)
|
||||||
|
*
|
||||||
|
* @Groups({"config_api"})
|
||||||
*/
|
*/
|
||||||
private $itemsPerPage;
|
private $itemsPerPage;
|
||||||
|
|
||||||
|
@ -58,6 +63,8 @@ class Config
|
||||||
*
|
*
|
||||||
* @Assert\NotBlank()
|
* @Assert\NotBlank()
|
||||||
* @ORM\Column(name="language", type="string", nullable=false)
|
* @ORM\Column(name="language", type="string", nullable=false)
|
||||||
|
*
|
||||||
|
* @Groups({"config_api"})
|
||||||
*/
|
*/
|
||||||
private $language;
|
private $language;
|
||||||
|
|
||||||
|
@ -65,6 +72,8 @@ class Config
|
||||||
* @var string
|
* @var string
|
||||||
*
|
*
|
||||||
* @ORM\Column(name="feed_token", type="string", nullable=true)
|
* @ORM\Column(name="feed_token", type="string", nullable=true)
|
||||||
|
*
|
||||||
|
* @Groups({"config_api"})
|
||||||
*/
|
*/
|
||||||
private $feedToken;
|
private $feedToken;
|
||||||
|
|
||||||
|
@ -77,6 +86,8 @@ class Config
|
||||||
* max = 100000,
|
* max = 100000,
|
||||||
* maxMessage = "validator.feed_limit_too_high"
|
* maxMessage = "validator.feed_limit_too_high"
|
||||||
* )
|
* )
|
||||||
|
*
|
||||||
|
* @Groups({"config_api"})
|
||||||
*/
|
*/
|
||||||
private $feedLimit;
|
private $feedLimit;
|
||||||
|
|
||||||
|
@ -84,6 +95,8 @@ class Config
|
||||||
* @var float
|
* @var float
|
||||||
*
|
*
|
||||||
* @ORM\Column(name="reading_speed", type="float", nullable=true)
|
* @ORM\Column(name="reading_speed", type="float", nullable=true)
|
||||||
|
*
|
||||||
|
* @Groups({"config_api"})
|
||||||
*/
|
*/
|
||||||
private $readingSpeed;
|
private $readingSpeed;
|
||||||
|
|
||||||
|
@ -98,6 +111,8 @@ class Config
|
||||||
* @var int
|
* @var int
|
||||||
*
|
*
|
||||||
* @ORM\Column(name="action_mark_as_read", type="integer", nullable=true, options={"default" = 0})
|
* @ORM\Column(name="action_mark_as_read", type="integer", nullable=true, options={"default" = 0})
|
||||||
|
*
|
||||||
|
* @Groups({"config_api"})
|
||||||
*/
|
*/
|
||||||
private $actionMarkAsRead;
|
private $actionMarkAsRead;
|
||||||
|
|
||||||
|
@ -105,6 +120,8 @@ class Config
|
||||||
* @var int
|
* @var int
|
||||||
*
|
*
|
||||||
* @ORM\Column(name="list_mode", type="integer", nullable=true)
|
* @ORM\Column(name="list_mode", type="integer", nullable=true)
|
||||||
|
*
|
||||||
|
* @Groups({"config_api"})
|
||||||
*/
|
*/
|
||||||
private $listMode;
|
private $listMode;
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,13 @@ class ConfigType extends AbstractType
|
||||||
$this->themes = array_combine(
|
$this->themes = array_combine(
|
||||||
$themes,
|
$themes,
|
||||||
array_map(function ($s) {
|
array_map(function ($s) {
|
||||||
return ucwords(strtolower(str_replace('-', ' ', $s)));
|
$cleanTheme = ucwords(strtolower(str_replace('-', ' ', $s)));
|
||||||
|
|
||||||
|
if ('Baggy' === $cleanTheme) {
|
||||||
|
$cleanTheme = 'Baggy (DEPRECATED)';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $cleanTheme;
|
||||||
}, $themes)
|
}, $themes)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -236,7 +236,9 @@ class ContentProxy
|
||||||
return $rawText;
|
return $rawText;
|
||||||
}
|
}
|
||||||
|
|
||||||
return iconv('UTF-8', 'UTF-8//IGNORE', $rawText);
|
mb_substitute_character('none');
|
||||||
|
|
||||||
|
return mb_convert_encoding($rawText, 'UTF-8', 'UTF-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -188,6 +188,10 @@ class DownloadImages
|
||||||
imagesavealpha($im, true);
|
imagesavealpha($im, true);
|
||||||
imagepng($im, $localPath, ceil(self::REGENERATE_PICTURES_QUALITY / 100 * 9));
|
imagepng($im, $localPath, ceil(self::REGENERATE_PICTURES_QUALITY / 100 * 9));
|
||||||
$this->logger->debug('DownloadImages: Re-creating png');
|
$this->logger->debug('DownloadImages: Re-creating png');
|
||||||
|
break;
|
||||||
|
case 'webp':
|
||||||
|
imagewebp($im, $localPath, self::REGENERATE_PICTURES_QUALITY);
|
||||||
|
$this->logger->debug('DownloadImages: Re-creating webp');
|
||||||
}
|
}
|
||||||
|
|
||||||
imagedestroy($im);
|
imagedestroy($im);
|
||||||
|
@ -333,6 +337,7 @@ class DownloadImages
|
||||||
'jpeg' => "\xFF\xD8\xFF",
|
'jpeg' => "\xFF\xD8\xFF",
|
||||||
'gif' => 'GIF',
|
'gif' => 'GIF',
|
||||||
'png' => "\x89\x50\x4e\x47\x0d\x0a",
|
'png' => "\x89\x50\x4e\x47\x0d\x0a",
|
||||||
|
'webp' => "\x52\x49\x46\x46",
|
||||||
];
|
];
|
||||||
$bytes = substr((string) $res->getBody(), 0, 8);
|
$bytes = substr((string) $res->getBody(), 0, 8);
|
||||||
|
|
||||||
|
@ -346,7 +351,7 @@ class DownloadImages
|
||||||
$this->logger->debug('DownloadImages: Checking extension (alternative)', ['ext' => $ext]);
|
$this->logger->debug('DownloadImages: Checking extension (alternative)', ['ext' => $ext]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!\in_array($ext, ['jpeg', 'jpg', 'gif', 'png'], true)) {
|
if (!\in_array($ext, ['jpeg', 'jpg', 'gif', 'png', 'webp'], true)) {
|
||||||
$this->logger->error('DownloadImages: Processed image with not allowed extension. Skipping: ' . $imagePath);
|
$this->logger->error('DownloadImages: Processed image with not allowed extension. Skipping: ' . $imagePath);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -161,8 +161,8 @@ class EntriesExport
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$book->setTitle($this->title);
|
$book->setTitle($this->title);
|
||||||
// Not needed, but included for the example, Language is mandatory, but EPub defaults to "en". Use RFC3066 Language codes, such as "en", "da", "fr" etc.
|
// EPub specification requires BCP47-compliant languages, thus we replace _ with -
|
||||||
$book->setLanguage($this->language);
|
$book->setLanguage(str_replace('_', '-', $this->language));
|
||||||
$book->setDescription('Some articles saved on my wallabag');
|
$book->setDescription('Some articles saved on my wallabag');
|
||||||
|
|
||||||
$book->setAuthor($this->author, $this->author);
|
$book->setAuthor($this->author, $this->author);
|
||||||
|
@ -527,6 +527,8 @@ class EntriesExport
|
||||||
*/
|
*/
|
||||||
private function getSanitizedFilename()
|
private function getSanitizedFilename()
|
||||||
{
|
{
|
||||||
return preg_replace('/[^A-Za-z0-9\- \']/', '', iconv('utf-8', 'us-ascii//TRANSLIT', $this->title));
|
$transliterator = \Transliterator::createFromRules(':: Any-Latin; :: Latin-ASCII; :: NFD; :: [:Nonspacing Mark:] Remove; :: NFC;', \Transliterator::FORWARD);
|
||||||
|
|
||||||
|
return preg_replace('/[^A-Za-z0-9\- \']/', '', $transliterator->transliterate($this->title));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,10 @@ class RuleBasedTagger
|
||||||
{
|
{
|
||||||
$rules = $this->getRulesForUser($entry->getUser());
|
$rules = $this->getRulesForUser($entry->getUser());
|
||||||
|
|
||||||
|
$clonedEntry = $this->fixEntry($entry);
|
||||||
|
|
||||||
foreach ($rules as $rule) {
|
foreach ($rules as $rule) {
|
||||||
if (!$this->rulerz->satisfies($entry, $rule->getRule())) {
|
if (!$this->rulerz->satisfies($clonedEntry, $rule->getRule())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,14 +63,22 @@ class RuleBasedTagger
|
||||||
public function tagAllForUser(User $user)
|
public function tagAllForUser(User $user)
|
||||||
{
|
{
|
||||||
$rules = $this->getRulesForUser($user);
|
$rules = $this->getRulesForUser($user);
|
||||||
$entries = [];
|
$entriesToUpdate = [];
|
||||||
$tagsCache = [];
|
$tagsCache = [];
|
||||||
|
|
||||||
foreach ($rules as $rule) {
|
$entries = $this->entryRepository
|
||||||
$qb = $this->entryRepository->getBuilderForAllByUser($user->getId());
|
->getBuilderForAllByUser($user->getId())
|
||||||
$entries = $this->rulerz->filter($qb, $rule->getRule());
|
->getQuery()
|
||||||
|
->getResult();
|
||||||
|
|
||||||
|
foreach ($entries as $entry) {
|
||||||
|
$clonedEntry = $this->fixEntry($entry);
|
||||||
|
|
||||||
|
foreach ($rules as $rule) {
|
||||||
|
if (!$this->rulerz->satisfies($clonedEntry, $rule->getRule())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($entries as $entry) {
|
|
||||||
foreach ($rule->getTags() as $label) {
|
foreach ($rule->getTags() as $label) {
|
||||||
// avoid new tag duplicate by manually caching them
|
// avoid new tag duplicate by manually caching them
|
||||||
if (!isset($tagsCache[$label])) {
|
if (!isset($tagsCache[$label])) {
|
||||||
|
@ -78,11 +88,13 @@ class RuleBasedTagger
|
||||||
$tag = $tagsCache[$label];
|
$tag = $tagsCache[$label];
|
||||||
|
|
||||||
$entry->addTag($tag);
|
$entry->addTag($tag);
|
||||||
|
|
||||||
|
$entriesToUpdate[] = $entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $entries;
|
return $entriesToUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,4 +126,15 @@ class RuleBasedTagger
|
||||||
{
|
{
|
||||||
return $user->getConfig()->getTaggingRules();
|
return $user->getConfig()->getTaggingRules();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update reading time on the fly to match the proper words per minute from the user.
|
||||||
|
*/
|
||||||
|
private function fixEntry(Entry $entry)
|
||||||
|
{
|
||||||
|
$clonedEntry = clone $entry;
|
||||||
|
$clonedEntry->setReadingTime($entry->getReadingTime() / $entry->getUser()->getConfig()->getReadingSpeed() * 200);
|
||||||
|
|
||||||
|
return $clonedEntry;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -385,9 +385,9 @@ class EntryRepository extends EntityRepository
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function findAllByTagId($userId, $tagId)
|
public function findAllByTagId($userId, $tagId, $sort = 'createdAt')
|
||||||
{
|
{
|
||||||
return $this->getSortedQueryBuilderByUser($userId)
|
return $this->getSortedQueryBuilderByUser($userId, $sort)
|
||||||
->innerJoin('e.tags', 't')
|
->innerJoin('e.tags', 't')
|
||||||
->andWhere('t.id = :tagId')->setParameter('tagId', $tagId)
|
->andWhere('t.id = :tagId')->setParameter('tagId', $tagId)
|
||||||
->getQuery()
|
->getQuery()
|
||||||
|
|
|
@ -163,7 +163,7 @@ config:
|
||||||
meaning: Význam
|
meaning: Význam
|
||||||
variables_available_description: 'Pro vytvoření pravidel štítkování mohou být použity následující proměnné a operátory:'
|
variables_available_description: 'Pro vytvoření pravidel štítkování mohou být použity následující proměnné a operátory:'
|
||||||
variables_available_title: Které proměnné a operátory mohu pro psaní pravidel použít?
|
variables_available_title: Které proměnné a operátory mohu pro psaní pravidel použít?
|
||||||
how_to_use_them_description: 'Předpokládejme, že chcete označit nové položky štítkem jako je « <i>krátké čtení</i> », pokud je doba čtení kratší než 3 minuty.<br />V takovém případě byste měli do pole <i>Pravidlo</i> zadat « readingTime <= 3 » a do pole <i>Štítky</i> zadat « <i>krátké čtení</i> ».<br />Několik štítků současně lze přidat jejich oddělením čárkou: « <i>krátké čtení, musím přečíst</i> »<br />Složitá pravidla lze zapsat pomocí předdefinovaných operátorů: if « <i>readingTime >= 5 AND domainName = "github.com"</i> » pak označit štítkem jako « <i>dlouhé čtení, GitHub</i> »'
|
how_to_use_them_description: 'Předpokládejme, že chcete označit nové položky štítkem jako je « <i>krátké čtení</i> », pokud je doba čtení kratší než 3 minuty.<br />V takovém případě byste měli do pole <i>Pravidlo</i> zadat « readingTime <= 3 » a do pole <i>Štítky</i> zadat « <i>krátké čtení</i> ».<br />Několik štítků současně lze přidat jejich oddělením čárkou: « <i>krátké čtení, musím přečíst</i> »<br />Složitá pravidla lze zapsat pomocí předdefinovaných operátorů: if « <i>readingTime >= 5 AND domainName = "www.php.net"</i> » pak označit štítkem jako « <i>dlouhé čtení, php</i> »'
|
||||||
how_to_use_them_title: Jak je použiji?
|
how_to_use_them_title: Jak je použiji?
|
||||||
tagging_rules_definition_description: Jsou to pravidla používaná programem wallabag k automatickému označování nových položek štítkem. <br />Pokaždé, když je přidána nová položky, všechna pravidla štítkování budou použita k přidání štítků, které jste nakonfigurovali, čímž vám ušetří potíže s ručním označováním vašich položek.
|
tagging_rules_definition_description: Jsou to pravidla používaná programem wallabag k automatickému označování nových položek štítkem. <br />Pokaždé, když je přidána nová položky, všechna pravidla štítkování budou použita k přidání štítků, které jste nakonfigurovali, čímž vám ušetří potíže s ručním označováním vašich položek.
|
||||||
tagging_rules_definition_title: Co znamenají „pravidla štítkování“?
|
tagging_rules_definition_title: Co znamenají „pravidla štítkování“?
|
||||||
|
|
|
@ -150,7 +150,7 @@ config:
|
||||||
tagging_rules_definition_title: Was bedeuten die „Tagging-Regeln“?
|
tagging_rules_definition_title: Was bedeuten die „Tagging-Regeln“?
|
||||||
tagging_rules_definition_description: Dies sind Regeln von wallabag, um neu hinzugefügte Einträge automatisch zu taggen.<br />Jedes Mal, wenn ein neuer Eintrag hinzugefügt wird, werden die Tagging-Regeln angewandt. Dies erleichtert dir die Arbeit, deine Einträge manuell zu kategorisieren.
|
tagging_rules_definition_description: Dies sind Regeln von wallabag, um neu hinzugefügte Einträge automatisch zu taggen.<br />Jedes Mal, wenn ein neuer Eintrag hinzugefügt wird, werden die Tagging-Regeln angewandt. Dies erleichtert dir die Arbeit, deine Einträge manuell zu kategorisieren.
|
||||||
how_to_use_them_title: Wie nutze ich sie?
|
how_to_use_them_title: Wie nutze ich sie?
|
||||||
how_to_use_them_description: 'Nehmen wir an, du möchtest deine Einträge als „<i>schnell lesbar</i>“ markiert, wenn die Lesezeit kürzer als drei Minuten ist.<br />In diesem Fall solltest du „readingTime <= 3“ in das Feld <i>Regel</i> und „<i>schnell lesbar</i>“ in das Feld <i>Tags</i> schreiben.<br />Mehrere Tags können gleichzeitig hinzugefügt werden, indem sie durch ein Komma getrennt werden: „<i>schnell lesbar, interessant</i>“.<br />Komplexe Regeln können durch vordefinierte Operatoren geschrieben werden: wenn „<i>readingTime >= 5 AND domainName = "github.com"</i>“ dann tagge als „<i>länger lesen, GitHub</i>“'
|
how_to_use_them_description: 'Nehmen wir an, du möchtest deine Einträge als „<i>schnell lesbar</i>“ markiert, wenn die Lesezeit kürzer als drei Minuten ist.<br />In diesem Fall solltest du „readingTime <= 3“ in das Feld <i>Regel</i> und „<i>schnell lesbar</i>“ in das Feld <i>Tags</i> schreiben.<br />Mehrere Tags können gleichzeitig hinzugefügt werden, indem sie durch ein Komma getrennt werden: „<i>schnell lesbar, interessant</i>“.<br />Komplexe Regeln können durch vordefinierte Operatoren geschrieben werden: wenn „<i>readingTime >= 5 AND domainName = "www.php.net"</i>“ dann tagge als „<i>länger lesen, php</i>“'
|
||||||
variables_available_title: Welche Variablen und Operatoren kann ich benutzen, um Regeln zu schreiben?
|
variables_available_title: Welche Variablen und Operatoren kann ich benutzen, um Regeln zu schreiben?
|
||||||
variables_available_description: 'Die folgenden Variablen und Operatoren können genutzt werden, um Tagging-Regeln zu erstellen:'
|
variables_available_description: 'Die folgenden Variablen und Operatoren können genutzt werden, um Tagging-Regeln zu erstellen:'
|
||||||
meaning: Bedeutung
|
meaning: Bedeutung
|
||||||
|
|
|
@ -158,7 +158,7 @@ config:
|
||||||
tagging_rules_definition_title: What does “tagging rules” mean?
|
tagging_rules_definition_title: What does “tagging rules” mean?
|
||||||
tagging_rules_definition_description: They are rules used by wallabag to automatically tag new entries.<br />Each time a new entry is added, all the tagging rules will be used to add the tags you configured, thus saving you the trouble of manually classifying your entries.
|
tagging_rules_definition_description: They are rules used by wallabag to automatically tag new entries.<br />Each time a new entry is added, all the tagging rules will be used to add the tags you configured, thus saving you the trouble of manually classifying your entries.
|
||||||
how_to_use_them_title: How do I use them?
|
how_to_use_them_title: How do I use them?
|
||||||
how_to_use_them_description: 'Let us assume you want to tag new entries as « <i>short reading</i> » when the reading time is under 3 minutes.<br />In that case, you should put « readingTime <= 3 » in the <i>Rule</i> field and « <i>short reading</i> » in the <i>Tags</i> field.<br />Several tags can added simultaneously by separating them with a comma: « <i>short reading, must read</i> »<br />Complex rules can be written by using predefined operators: if « <i>readingTime >= 5 AND domainName = "github.com"</i> » then tag as « <i>long reading, GitHub </i> »'
|
how_to_use_them_description: 'Let us assume you want to tag new entries as « <i>short reading</i> » when the reading time is under 3 minutes.<br />In that case, you should put « readingTime <= 3 » in the <i>Rule</i> field and « <i>short reading</i> » in the <i>Tags</i> field.<br />Several tags can added simultaneously by separating them with a comma: « <i>short reading, must read</i> »<br />Complex rules can be written by using predefined operators: if « <i>readingTime >= 5 AND domainName = "www.php.net"</i> » then tag as « <i>long reading, php</i> »'
|
||||||
variables_available_title: Which variables and operators can I use to write rules?
|
variables_available_title: Which variables and operators can I use to write rules?
|
||||||
variables_available_description: 'The following variables and operators can be used to create tagging rules:'
|
variables_available_description: 'The following variables and operators can be used to create tagging rules:'
|
||||||
meaning: Meaning
|
meaning: Meaning
|
||||||
|
@ -241,6 +241,7 @@ entry:
|
||||||
delete: Delete
|
delete: Delete
|
||||||
export_title: Export
|
export_title: Export
|
||||||
show_same_domain: Show articles with the same domain
|
show_same_domain: Show articles with the same domain
|
||||||
|
assign_search_tag: Assign this search as a tag to each result
|
||||||
filters:
|
filters:
|
||||||
title: Filters
|
title: Filters
|
||||||
status_label: Status
|
status_label: Status
|
||||||
|
|
|
@ -157,7 +157,7 @@ config:
|
||||||
tagging_rules_definition_title: '¿Qué significa «reglas de etiquetado»?'
|
tagging_rules_definition_title: '¿Qué significa «reglas de etiquetado»?'
|
||||||
tagging_rules_definition_description: 'Son las reglas usadas por wallabag para etiquetar automáticamente los nuevos artículos.<br />Cada vez que un artículo es añadido, todas las reglas de etiquetado automático serán usadas para etiquetarlo, ayudándote a clasificar automáticamente tus artículos.'
|
tagging_rules_definition_description: 'Son las reglas usadas por wallabag para etiquetar automáticamente los nuevos artículos.<br />Cada vez que un artículo es añadido, todas las reglas de etiquetado automático serán usadas para etiquetarlo, ayudándote a clasificar automáticamente tus artículos.'
|
||||||
how_to_use_them_title: '¿Cómo se utilizan?'
|
how_to_use_them_title: '¿Cómo se utilizan?'
|
||||||
how_to_use_them_description: 'Supongamos que quiere etiquetar los artículos nuevos como « <i>lectura corta</i> » cuando el tiempo de lectura sea menos de 3 minutos.<br /> En este caso, debe poner « readingTime <= 3 » en el campo <i>Regla</i> y « <i>lectura corta</i> » en el campo <i>Etiquetas</i>.<br />Se pueden añadir varias etiquetas al mismo tiempo separadas por comas: « <i>lectura corta, lectura obligada</i> »<br />Se pueden escribir reglas complejas utilizando los operadores predefinidos: si « <i>readingTime >= 5 AND domainName = "github.com"</i> » entonces etiqueta como « <i>lectura larga, GitHub </i> »'
|
how_to_use_them_description: 'Supongamos que quiere etiquetar los artículos nuevos como « <i>lectura corta</i> » cuando el tiempo de lectura sea menos de 3 minutos.<br /> En este caso, debe poner « readingTime <= 3 » en el campo <i>Regla</i> y « <i>lectura corta</i> » en el campo <i>Etiquetas</i>.<br />Se pueden añadir varias etiquetas al mismo tiempo separadas por comas: « <i>lectura corta, lectura obligada</i> »<br />Se pueden escribir reglas complejas utilizando los operadores predefinidos: si « <i>readingTime >= 5 AND domainName = "www.php.net"</i> » entonces etiqueta como « <i>lectura larga, php</i> »'
|
||||||
variables_available_title: '¿Qué variables y operadores se pueden utilizar para escribir las reglas?'
|
variables_available_title: '¿Qué variables y operadores se pueden utilizar para escribir las reglas?'
|
||||||
variables_available_description: 'Las siguientes variables y operadores se pueden utilizar para crear reglas de etiquetado:'
|
variables_available_description: 'Las siguientes variables y operadores se pueden utilizar para crear reglas de etiquetado:'
|
||||||
meaning: 'Significado'
|
meaning: 'Significado'
|
||||||
|
|
|
@ -158,7 +158,7 @@ config:
|
||||||
tagging_rules_definition_title: Que signifient les règles d'étiquetage automatiques ?
|
tagging_rules_definition_title: Que signifient les règles d'étiquetage automatiques ?
|
||||||
tagging_rules_definition_description: Ce sont des règles utilisées par wallabag pour classer automatiquement vos nouveaux articles.<br />À chaque fois qu’un nouvel article est ajouté, toutes les règles d'étiquetage automatiques seront utilisées afin d’ajouter les tags que vous avez configurés, vous épargnant ainsi l’effort de classifier vos articles manuellement.
|
tagging_rules_definition_description: Ce sont des règles utilisées par wallabag pour classer automatiquement vos nouveaux articles.<br />À chaque fois qu’un nouvel article est ajouté, toutes les règles d'étiquetage automatiques seront utilisées afin d’ajouter les tags que vous avez configurés, vous épargnant ainsi l’effort de classifier vos articles manuellement.
|
||||||
how_to_use_them_title: Comment les utiliser ?
|
how_to_use_them_title: Comment les utiliser ?
|
||||||
how_to_use_them_description: 'Imaginons que voulez attribuer aux nouveaux articles l''étiquette « <i>lecture courte</i> » lorsque le temps de lecture est inférieur à 3 minutes.<br />Dans ce cas, vous devriez mettre « readingTime <= 3 » dans le champ <i>Règle</i> et « <i>lecture courte</i> » dans le champ <i>Tag</i>.<br />Plusieurs tags peuvent être ajoutés simultanément en les séparant par des virgules : « <i>lecture courte, à lire</i> »<br />Des règles complexes peuvent être créées en utilisant des opérateurs prédéfinis: si « <i>readingTime >= 5 AND domainName = "github.com"</i> » alors attribuer les étiquettes « <i>lecture longue, GitHub</i> »'
|
how_to_use_them_description: 'Imaginons que voulez attribuer aux nouveaux articles l''étiquette « <i>lecture courte</i> » lorsque le temps de lecture est inférieur à 3 minutes.<br />Dans ce cas, vous devriez mettre « readingTime <= 3 » dans le champ <i>Règle</i> et « <i>lecture courte</i> » dans le champ <i>Tag</i>.<br />Plusieurs tags peuvent être ajoutés simultanément en les séparant par des virgules : « <i>lecture courte, à lire</i> »<br />Des règles complexes peuvent être créées en utilisant des opérateurs prédéfinis: si « <i>readingTime >= 5 AND domainName = "www.php.net"</i> » alors attribuer les étiquettes « <i>lecture longue, php</i> »'
|
||||||
variables_available_title: Quelles variables et opérateurs puis-je utiliser pour écrire des règles ?
|
variables_available_title: Quelles variables et opérateurs puis-je utiliser pour écrire des règles ?
|
||||||
variables_available_description: 'Les variables et opérateurs suivants peuvent être utilisés pour écrire des règles d''étiquetage automatiques :'
|
variables_available_description: 'Les variables et opérateurs suivants peuvent être utilisés pour écrire des règles d''étiquetage automatiques :'
|
||||||
meaning: Signification
|
meaning: Signification
|
||||||
|
|
|
@ -203,7 +203,7 @@ config:
|
||||||
title: PMF
|
title: PMF
|
||||||
form_rules:
|
form_rules:
|
||||||
faq:
|
faq:
|
||||||
how_to_use_them_description: 'Demos por feito que queres etiquetar as novas entradas con « <i>lectura rápida</i> » cando o tempo de lectura non supera os 3 minutos.<br />Neste caso, tes que poñer « TempodeLectura <= 3 » no campo da <i>Regra</i> e « <i>lectura rápida</i> » no campo da <i>Etiqueta</i> .<br />Podes engadir varias etiquetas ó mesmo tempo separándoas cunha vírgula: « <i>lectura rápida, teño que ler</i> »<br />Pódense establecer regras complexas usando os operadores predefinidos: se o « <i>readingTime >= 5 AND domainName = "github.com"</i> » entón etiquetar como « <i>lectura longa, GitHub </i> »'
|
how_to_use_them_description: 'Demos por feito que queres etiquetar as novas entradas con « <i>lectura rápida</i> » cando o tempo de lectura non supera os 3 minutos.<br />Neste caso, tes que poñer « TempodeLectura <= 3 » no campo da <i>Regra</i> e « <i>lectura rápida</i> » no campo da <i>Etiqueta</i> .<br />Podes engadir varias etiquetas ó mesmo tempo separándoas cunha vírgula: « <i>lectura rápida, teño que ler</i> »<br />Pódense establecer regras complexas usando os operadores predefinidos: se o « <i>readingTime >= 5 AND domainName = "www.php.net"</i> » entón etiquetar como « <i>lectura longa, php</i> »'
|
||||||
operator_description:
|
operator_description:
|
||||||
notmatches: 'Comproba que o <i>obxecto</i> non contén a <i>busca</i> (non dif. maiúsculas).<br />Exemplo: <code>título non contén "saúde"</code>'
|
notmatches: 'Comproba que o <i>obxecto</i> non contén a <i>busca</i> (non dif. maiúsculas).<br />Exemplo: <code>título non contén "saúde"</code>'
|
||||||
matches: 'Comproba que un <i>obxecto</i> concorda coa <i>busca</i> (dif. maius.-minus.).<br />Exemplo: <code>título contén "saúde"</code>'
|
matches: 'Comproba que un <i>obxecto</i> concorda coa <i>busca</i> (dif. maius.-minus.).<br />Exemplo: <code>título contén "saúde"</code>'
|
||||||
|
@ -312,7 +312,7 @@ config:
|
||||||
table_method: Método
|
table_method: Método
|
||||||
googleTwoFactor_label: Usando app OTP (usa unha app como andOTP, FreeOTP, Authy ou Google Authenticator, para obter o código único)
|
googleTwoFactor_label: Usando app OTP (usa unha app como andOTP, FreeOTP, Authy ou Google Authenticator, para obter o código único)
|
||||||
emailTwoFactor_label: Utilizando email (recibirás código por email)
|
emailTwoFactor_label: Utilizando email (recibirás código por email)
|
||||||
login_label: Conexión (non se pode cambiar
|
login_label: Identificador (non se pode cambiar)
|
||||||
email_label: Email
|
email_label: Email
|
||||||
name_label: Nome
|
name_label: Nome
|
||||||
two_factor_description: Se activas o segundo factor de autenticación recibirás un email cun código en cada nova conexión que aínda non verificases.
|
two_factor_description: Se activas o segundo factor de autenticación recibirás un email cun código en cada nova conexión que aínda non verificases.
|
||||||
|
@ -391,11 +391,11 @@ security:
|
||||||
login:
|
login:
|
||||||
cancel: Cancelar
|
cancel: Cancelar
|
||||||
password: Contrasinal
|
password: Contrasinal
|
||||||
username: Nome de usuaria
|
username: Identificador
|
||||||
register: Abre unha conta
|
register: Crea unha conta
|
||||||
submit: Conectar
|
submit: Acceder
|
||||||
forgot_password: Esqueceches o contrasinal?
|
forgot_password: Esqueceches o contrasinal?
|
||||||
keep_logged_in: Manterme conectada
|
keep_logged_in: Manter a sesión
|
||||||
page_title: Benvida a wallabag!
|
page_title: Benvida a wallabag!
|
||||||
import:
|
import:
|
||||||
wallabag_v2:
|
wallabag_v2:
|
||||||
|
@ -530,7 +530,7 @@ developer:
|
||||||
paragraph_7: Esta chamada devolverá todas as entradas do teu usuario.
|
paragraph_7: Esta chamada devolverá todas as entradas do teu usuario.
|
||||||
paragraph_6: 'O access_token é útil para chamar ao punto de acceso da API. Por exemplo:'
|
paragraph_6: 'O access_token é útil para chamar ao punto de acceso da API. Por exemplo:'
|
||||||
paragraph_5: 'A API responderá con algo semellante a:'
|
paragraph_5: 'A API responderá con algo semellante a:'
|
||||||
paragraph_4: 'Agora, crea o token (substitúe client_id, client_secret, username e password cos valores axeitados):'
|
paragraph_4: 'Agora, crea o token (substitúe client_id, client_secret, identificador e contrasinal cos valores axeitados):'
|
||||||
paragraph_3: Para crear este token, tes que <a href="%link%">crear un novo cliente</a>.
|
paragraph_3: Para crear este token, tes que <a href="%link%">crear un novo cliente</a>.
|
||||||
paragraph_2: Precisas un token para comunicarte entre a túa app de terceiros e a API de wallabag.
|
paragraph_2: Precisas un token para comunicarte entre a túa app de terceiros e a API de wallabag.
|
||||||
paragraph_1: As seguintes ordes fan uso da <a href="https://github.com/jkbrzt/httpie">biblioteca HTTPie</a>. Comproba que está instalada no teu sistema antes de utilizala.
|
paragraph_1: As seguintes ordes fan uso da <a href="https://github.com/jkbrzt/httpie">biblioteca HTTPie</a>. Comproba que está instalada no teu sistema antes de utilizala.
|
||||||
|
@ -660,7 +660,7 @@ site_credential:
|
||||||
save: Gardar
|
save: Gardar
|
||||||
password_label: Contrasinal
|
password_label: Contrasinal
|
||||||
host_label: Servidor (subdominio.exemplo.org, .exemplo.org, etc.)
|
host_label: Servidor (subdominio.exemplo.org, .exemplo.org, etc.)
|
||||||
username_label: Conectar
|
username_label: Identificador
|
||||||
list:
|
list:
|
||||||
create_new_one: Crear unha nova credencial
|
create_new_one: Crear unha nova credencial
|
||||||
no: Non
|
no: Non
|
||||||
|
@ -673,7 +673,7 @@ site_credential:
|
||||||
page_title: Xestión das credenciais do sitio
|
page_title: Xestión das credenciais do sitio
|
||||||
user:
|
user:
|
||||||
search:
|
search:
|
||||||
placeholder: Filtrar por nome de usuaria ou email
|
placeholder: Filtrar por identificador ou email
|
||||||
form:
|
form:
|
||||||
back_to_list: Volver á lista
|
back_to_list: Volver á lista
|
||||||
delete_confirm: Tes a certeza?
|
delete_confirm: Tes a certeza?
|
||||||
|
@ -681,14 +681,14 @@ user:
|
||||||
save: Gardar
|
save: Gardar
|
||||||
twofactor_google_label: Segundo factor de autenticación por app OTP
|
twofactor_google_label: Segundo factor de autenticación por app OTP
|
||||||
twofactor_email_label: Segundo factor de autenticación por email
|
twofactor_email_label: Segundo factor de autenticación por email
|
||||||
last_login_label: Última conexión
|
last_login_label: Último acceso
|
||||||
enabled_label: Activado
|
enabled_label: Activado
|
||||||
email_label: Email
|
email_label: Email
|
||||||
plain_password_label: ????
|
plain_password_label: ????
|
||||||
repeat_new_password_label: Repetir o novo contrasinal
|
repeat_new_password_label: Repetir o novo contrasinal
|
||||||
password_label: Contrasinal
|
password_label: Contrasinal
|
||||||
name_label: Nome
|
name_label: Nome
|
||||||
username_label: Nome de usuaria
|
username_label: Identificador
|
||||||
list:
|
list:
|
||||||
create_new_one: Crear nova usuaria
|
create_new_one: Crear nova usuaria
|
||||||
no: Non
|
no: Non
|
||||||
|
|
|
@ -176,7 +176,7 @@ config:
|
||||||
title: ČPP
|
title: ČPP
|
||||||
meaning: Značenje
|
meaning: Značenje
|
||||||
variables_available_title: Koje varijable i operateri mogu koristiti za pisanje pravila?
|
variables_available_title: Koje varijable i operateri mogu koristiti za pisanje pravila?
|
||||||
how_to_use_them_description: 'Pretpostavimo da želiš označiti nove zapise kao <i>kratko čitanje</i> kad je vrijeme čitanja manje od 3 minute.<br />U tom slučaju, postavi „readingTime <= 3” u polju <i>Pravilo</i> i <i>kratko čitanje</i> u polju <i>Oznake</i>.<br />Moguće je dodati više oznaka istovremeno, odvajajući ih zarezom: „<i>kratko čitanje, moram čitati</i>”<br />Složena pravila mogu se napisati pomoću unaprijed definiranih operatora: ako „<i>readingTime >= 5 AND domainName = "github.com"</i>”, onda označi kao „<i>dugo čitanje, GitHub </i>”'
|
how_to_use_them_description: 'Pretpostavimo da želiš označiti nove zapise kao <i>kratko čitanje</i> kad je vrijeme čitanja manje od 3 minute.<br />U tom slučaju, postavi „readingTime <= 3” u polju <i>Pravilo</i> i <i>kratko čitanje</i> u polju <i>Oznake</i>.<br />Moguće je dodati više oznaka istovremeno, odvajajući ih zarezom: „<i>kratko čitanje, moram čitati</i>”<br />Složena pravila mogu se napisati pomoću unaprijed definiranih operatora: ako „<i>readingTime >= 5 AND domainName = "www.php.net"</i>”, onda označi kao „<i>dugo čitanje, php</i>”'
|
||||||
delete_rule_label: ukloni
|
delete_rule_label: ukloni
|
||||||
edit_rule_label: uredi
|
edit_rule_label: uredi
|
||||||
if_label: ako
|
if_label: ako
|
||||||
|
|
|
@ -129,7 +129,7 @@ config:
|
||||||
tagging_rules_definition_title: A „címkézési szabályok” mit jelent?
|
tagging_rules_definition_title: A „címkézési szabályok” mit jelent?
|
||||||
tagging_rules_definition_description: Ezek olyan szabályok amiket a Wallabag használ arra, hogy automatikusan felcímkézze az új bejegyzéseket.<br />Minden egyes alkalommal, amikor egy újabb bejegyzés hozzáadásra kerül, minden címkézési szabály fel lesz használva a beállított címkék hozzáadására, így mentve meg attól a problémától, hogy kézzel osztályozza a bejegyzéseit.
|
tagging_rules_definition_description: Ezek olyan szabályok amiket a Wallabag használ arra, hogy automatikusan felcímkézze az új bejegyzéseket.<br />Minden egyes alkalommal, amikor egy újabb bejegyzés hozzáadásra kerül, minden címkézési szabály fel lesz használva a beállított címkék hozzáadására, így mentve meg attól a problémától, hogy kézzel osztályozza a bejegyzéseit.
|
||||||
how_to_use_them_title: Hogyan használhatom ezeket?
|
how_to_use_them_title: Hogyan használhatom ezeket?
|
||||||
how_to_use_them_description: 'Tételezzük fel, hogy szeretné az új bejegyzéseket úgy címkézni mint « <i>rövid olvasnivaló</i> », ha az elolvasási idejük 3 perc alatt van.<br />Ebben az esetben ezt írja be a <i>Szabály</i> mezőbe: « readingTime <= 3 », a <i>Címkék</i> mezőbe pedig: « <i>rövid olvasnivaló</i> ».<br />Több címke is hozzáadható egyszerre, ha vesszővel elválasztja őket: « <i>rövid olvasnivaló, el kell olvasni</i> »<br />Összetett szabályok írhatók előre definiált operátorok használatával: ha « <i>readingTime >= 5 AND domainName = "github.com"</i> » akkor címkézd meg mint « <i>hosszú olvasnivaló, GitHub</i> »'
|
how_to_use_them_description: 'Tételezzük fel, hogy szeretné az új bejegyzéseket úgy címkézni mint « <i>rövid olvasnivaló</i> », ha az elolvasási idejük 3 perc alatt van.<br />Ebben az esetben ezt írja be a <i>Szabály</i> mezőbe: « readingTime <= 3 », a <i>Címkék</i> mezőbe pedig: « <i>rövid olvasnivaló</i> ».<br />Több címke is hozzáadható egyszerre, ha vesszővel elválasztja őket: « <i>rövid olvasnivaló, el kell olvasni</i> »<br />Összetett szabályok írhatók előre definiált operátorok használatával: ha « <i>readingTime >= 5 AND domainName = "www.php.net"</i> » akkor címkézd meg mint « <i>hosszú olvasnivaló, php</i> »'
|
||||||
variables_available_title: Milyen változókat és operátorokat használhatok a szabályok írásához?
|
variables_available_title: Milyen változókat és operátorokat használhatok a szabályok írásához?
|
||||||
variables_available_description: 'A következő változók és operátorok használhatók címkézési szabályok létrehozásához:'
|
variables_available_description: 'A következő változók és operátorok használhatók címkézési szabályok létrehozásához:'
|
||||||
meaning: Jelentés
|
meaning: Jelentés
|
||||||
|
|
|
@ -140,7 +140,7 @@ config:
|
||||||
tagging_rules_definition_title: Cosa significa «regole di etichettatura»?
|
tagging_rules_definition_title: Cosa significa «regole di etichettatura»?
|
||||||
tagging_rules_definition_description: Sono regole utilizzate da wallabag per etichettare automaticamente i contenuti.<br />Ogni volta che viene aggiunto un contenuto, tutte le regole di etichettatura vengono utilizzate per aggiungere le etichette configurate, risparmiandoti il lavoro di classificare i contenuti manualmente.
|
tagging_rules_definition_description: Sono regole utilizzate da wallabag per etichettare automaticamente i contenuti.<br />Ogni volta che viene aggiunto un contenuto, tutte le regole di etichettatura vengono utilizzate per aggiungere le etichette configurate, risparmiandoti il lavoro di classificare i contenuti manualmente.
|
||||||
how_to_use_them_title: Come si usano?
|
how_to_use_them_title: Come si usano?
|
||||||
how_to_use_them_description: 'Diciamo che vuoi etichettare un contenuto come « <i>lettura veloce</i> » quando il tempo di lettura è inferiore ai 3 minuti.<br />In questo case, devi mettere « readingTime <= 3 » nel campo <i>Regola</i> e « <i>lettura veloce</i> » nel campo <i>Etichette</i>.<br />Molte etichette si possono aggiungere contemporanemente separandole con una virgola: « <i>lettura veloce, da leggere</i> »<br />Regole complesse possono essere scritte utilizzando gli operatori predefiniti: se « <i>readingTime >= 5 AND domainName = "github.com"</i> » allora etichetta « <i>lettura lunga, GitHub </i> »'
|
how_to_use_them_description: 'Diciamo che vuoi etichettare un contenuto come « <i>lettura veloce</i> » quando il tempo di lettura è inferiore ai 3 minuti.<br />In questo case, devi mettere « readingTime <= 3 » nel campo <i>Regola</i> e « <i>lettura veloce</i> » nel campo <i>Etichette</i>.<br />Molte etichette si possono aggiungere contemporanemente separandole con una virgola: « <i>lettura veloce, da leggere</i> »<br />Regole complesse possono essere scritte utilizzando gli operatori predefiniti: se « <i>readingTime >= 5 AND domainName = "www.php.net"</i> » allora etichetta « <i>lettura lunga, php</i> »'
|
||||||
variables_available_title: Quali operatori e variabili posso utilizzare per scrivere delle regole?
|
variables_available_title: Quali operatori e variabili posso utilizzare per scrivere delle regole?
|
||||||
variables_available_description: 'I seguenti operatori e variabili posso essere utilizzati per scrivere regole di etichettatura:'
|
variables_available_description: 'I seguenti operatori e variabili posso essere utilizzati per scrivere regole di etichettatura:'
|
||||||
meaning: Significato
|
meaning: Significato
|
||||||
|
|
|
@ -165,7 +165,7 @@ config:
|
||||||
notmatches: <i>対象</i>が<i>検索</i>と一致しないことをテストする(大文字小文字の区別なし)。<br />例:<code>title notmatches "football"</code>
|
notmatches: <i>対象</i>が<i>検索</i>と一致しないことをテストする(大文字小文字の区別なし)。<br />例:<code>title notmatches "football"</code>
|
||||||
matches: <i>対象</i>が<i>検索</i>と一致するかテストする(大文字小文字の区別なし)。<br />例:<code>title matches "football"</code>
|
matches: <i>対象</i>が<i>検索</i>と一致するかテストする(大文字小文字の区別なし)。<br />例:<code>title matches "football"</code>
|
||||||
tagging_rules_definition_description: wallabag ではルールを使用することで新しい記事へ自動的にタグ付けする事ができます。<br />新しい記事が追加されるたびに、あなたが設定したすべてのタグ付けルールを使用してタグが追加されるので、記事を手動で分類する手間が省けます。
|
tagging_rules_definition_description: wallabag ではルールを使用することで新しい記事へ自動的にタグ付けする事ができます。<br />新しい記事が追加されるたびに、あなたが設定したすべてのタグ付けルールを使用してタグが追加されるので、記事を手動で分類する手間が省けます。
|
||||||
how_to_use_them_description: 'あなたは読了時間が3分以下の時に新しい記事へ « <i>短い文章</i> » のタグ付けをしたいとします。<br />この場合、<i>ルール</i>に « readingTime <= 3 »と<i>タグ</i>に « <i>短い文章</i> » を設定します。<br />コンマで区切ることにより複数のタグを追加することができます: « <i>短い文章, 必読</i> »<br />演算子を使用することにより複雑なルールを書くことができます: もし « <i>readingTime >= 5 AND domainName = "github.com"</i> »ならばタグ付け « <i>長い文章, GitHub </i> »'
|
how_to_use_them_description: 'あなたは読了時間が3分以下の時に新しい記事へ « <i>短い文章</i> » のタグ付けをしたいとします。<br />この場合、<i>ルール</i>に « readingTime <= 3 »と<i>タグ</i>に « <i>短い文章</i> » を設定します。<br />コンマで区切ることにより複数のタグを追加することができます: « <i>短い文章, 必読</i> »<br />演算子を使用することにより複雑なルールを書くことができます: もし « <i>readingTime >= 5 AND domainName = "www.php.net"</i> »ならばタグ付け « <i>長い文章, php</i> »'
|
||||||
delete_rule_label: 削除
|
delete_rule_label: 削除
|
||||||
export: エクスポート
|
export: エクスポート
|
||||||
import_submit: インポート
|
import_submit: インポート
|
||||||
|
|
|
@ -400,7 +400,7 @@ config:
|
||||||
title: 문서 제목
|
title: 문서 제목
|
||||||
label: 변수
|
label: 변수
|
||||||
tagging_rules_definition_description: wallabag 에서 자동으로 새 문서에 태그를 지정하는 데 사용하는 규칙입니다. <br /> 태그 지정 규칙이 새 문서가 추가 될 때마다 태그를 구성하는 데 사용되므로, 수동으로 분류하는 수고를 덜 수 있습니다.
|
tagging_rules_definition_description: wallabag 에서 자동으로 새 문서에 태그를 지정하는 데 사용하는 규칙입니다. <br /> 태그 지정 규칙이 새 문서가 추가 될 때마다 태그를 구성하는 데 사용되므로, 수동으로 분류하는 수고를 덜 수 있습니다.
|
||||||
how_to_use_them_description: '읽기 시간이 3 분 미만인 경우 «<i> 짧은 읽기 </i>» 와 같은 새 기사에 태그를 지정한다고 가정합니다. <br />이 경우 <i> 규칙</i> 을 입력해야합니다. <i>태그</i> 필드에 « readingTime <= 3 » 을 입력하고 « <i>짧은 읽기</i>» 를 입력하십시오. <br /> 여러 태그를 쉼표로구분하여 한 번에 추가 할 수 있습니다: « <i> 짧은 읽기, 반드시 읽기</i> » <br /> 사전 정의 된 연산자를 사용하여 복잡한 규칙을 작성할 수 있습니다: 만약 « <i>readingTime >= 5 AND domainName = "github .com"</i> » 다음으로 태그 «<i> 긴 읽기, GitHub </i>»'
|
how_to_use_them_description: '읽기 시간이 3 분 미만인 경우 «<i> 짧은 읽기 </i>» 와 같은 새 기사에 태그를 지정한다고 가정합니다. <br />이 경우 <i> 규칙</i> 을 입력해야합니다. <i>태그</i> 필드에 « readingTime <= 3 » 을 입력하고 « <i>짧은 읽기</i>» 를 입력하십시오. <br /> 여러 태그를 쉼표로구분하여 한 번에 추가 할 수 있습니다: « <i> 짧은 읽기, 반드시 읽기</i> » <br /> 사전 정의 된 연산자를 사용하여 복잡한 규칙을 작성할 수 있습니다: 만약 « <i>readingTime >= 5 AND domainName = "www.php.net"</i> » 다음으로 태그 «<i> 긴 읽기, php</i>»'
|
||||||
operator_description:
|
operator_description:
|
||||||
and: 하나의 규칙 그리고 다른 규칙
|
and: 하나의 규칙 그리고 다른 규칙
|
||||||
or: 하나의 규칙 또는 다른 규칙
|
or: 하나의 규칙 또는 다른 규칙
|
||||||
|
|
|
@ -102,7 +102,7 @@ config:
|
||||||
how_to_use_them_title: Hoe gebruik is ze?
|
how_to_use_them_title: Hoe gebruik is ze?
|
||||||
tagging_rules_definition_title: Wat betekend "label regels"?
|
tagging_rules_definition_title: Wat betekend "label regels"?
|
||||||
title: FAQ
|
title: FAQ
|
||||||
how_to_use_them_description: 'Laten we aannemen dat u nieuwe vermeldingen wilt labelen als « <i>korte lezing</i> » wanneer de leestijd minder dan 3 minuten bedraagt.<br />In dat geval moet u « readingTime <= 3 » in het <i>Regelveld</i> en « <i>korte lezing</i> » in het <i>Labels</i> veld.<br />Meerdere labels kunnen tegelijkertijd worden toegevoegd door ze te scheiden met een komma:« <i>korte lezing, belangrijk</i> »<br />Complexe regels kunnen worden geschreven met behulp van vooraf gedefinieerde operators: if « <i>readingTime >= 5 AND domainName = "github.com"</i> » label dan als« <i>lange lezing, GitHub </i> »'
|
how_to_use_them_description: 'Laten we aannemen dat u nieuwe vermeldingen wilt labelen als « <i>korte lezing</i> » wanneer de leestijd minder dan 3 minuten bedraagt.<br />In dat geval moet u « readingTime <= 3 » in het <i>Regelveld</i> en « <i>korte lezing</i> » in het <i>Labels</i> veld.<br />Meerdere labels kunnen tegelijkertijd worden toegevoegd door ze te scheiden met een komma:« <i>korte lezing, belangrijk</i> »<br />Complexe regels kunnen worden geschreven met behulp van vooraf gedefinieerde operators: if « <i>readingTime >= 5 AND domainName = "www.php.net"</i> » label dan als« <i>lange lezing, php</i> »'
|
||||||
tags_label: Labels
|
tags_label: Labels
|
||||||
rule_label: Regel
|
rule_label: Regel
|
||||||
edit_rule_label: wijzig
|
edit_rule_label: wijzig
|
||||||
|
|
|
@ -136,7 +136,7 @@ config:
|
||||||
tagging_rules_definition_title: Qué significa las règlas d'etiquetas automaticas ?
|
tagging_rules_definition_title: Qué significa las règlas d'etiquetas automaticas ?
|
||||||
tagging_rules_definition_description: Son de règlas utilizadas per wallabag per classar automaticament vòstres novèls articles.<br />Cada còp qu'un novèl article es apondut, totas las règlas d'etiquetas automaticas seràn utilizadas per ajustar d'etiquetas qu'avètz configuradas, en vos esparnhant l'esfòrç de classificar vòstres articles manualament.
|
tagging_rules_definition_description: Son de règlas utilizadas per wallabag per classar automaticament vòstres novèls articles.<br />Cada còp qu'un novèl article es apondut, totas las règlas d'etiquetas automaticas seràn utilizadas per ajustar d'etiquetas qu'avètz configuradas, en vos esparnhant l'esfòrç de classificar vòstres articles manualament.
|
||||||
how_to_use_them_title: Cossí las utilizar ?
|
how_to_use_them_title: Cossí las utilizar ?
|
||||||
how_to_use_them_description: Imaginem que volètz atribuir als novèls article l'etiqueta « <i>lectura corta</i> » quand lo temps per legir es inferior a 3 minutas.<br />Dins aquel cas, deuriatz metre « readingTime <= 3 » dins lo camp <i>Règla</i> e « <i>lectura corta</i> » dins lo camp <i>Etiqueta</i>.<br />Mai d'una etiquetas pòdon èsser apondudas simultanèament ne las separant amb de virgulas : « <i>lectura corta, per ligir</i> »<br />De règlas complèxas pòdon èsser creadas n'emplegant d'operators predefinits : se « <i>readingTime >= 5 AND domainName = "github.com"</i> » alara atribuir las etiquetas « <i>lectura longa, github </i> »
|
how_to_use_them_description: Imaginem que volètz atribuir als novèls article l'etiqueta « <i>lectura corta</i> » quand lo temps per legir es inferior a 3 minutas.<br />Dins aquel cas, deuriatz metre « readingTime <= 3 » dins lo camp <i>Règla</i> e « <i>lectura corta</i> » dins lo camp <i>Etiqueta</i>.<br />Mai d'una etiquetas pòdon èsser apondudas simultanèament ne las separant amb de virgulas : « <i>lectura corta, per ligir</i> »<br />De règlas complèxas pòdon èsser creadas n'emplegant d'operators predefinits : se « <i>readingTime >= 5 AND domainName = "www.php.net"</i> » alara atribuir las etiquetas « <i>lectura longa, php</i> »
|
||||||
variables_available_title: Quinas variablas e operators pòdi utilizar per escriure de règlas ?
|
variables_available_title: Quinas variablas e operators pòdi utilizar per escriure de règlas ?
|
||||||
variables_available_description: "Las variablas e operators seguents pòdon èsser utilizats per escriure de règlas d'etiquetas automaticas :"
|
variables_available_description: "Las variablas e operators seguents pòdon èsser utilizats per escriure de règlas d'etiquetas automaticas :"
|
||||||
meaning: Significacion
|
meaning: Significacion
|
||||||
|
|
|
@ -150,7 +150,7 @@ config:
|
||||||
tagging_rules_definition_title: Co oznaczają « reguły tagowania » ?
|
tagging_rules_definition_title: Co oznaczają « reguły tagowania » ?
|
||||||
tagging_rules_definition_description: Istnieją reguły używane przez wallabag służące do automatycznego tagowania nowych wpisów.<br />Za każdym razem kiedy dodasz nowy wpis, zostaną użyte wszystkie skonfigurowane przez ciebie reguły. Dzięki temu unikniesz konieczności ręcznego ich klasyfikowania.
|
tagging_rules_definition_description: Istnieją reguły używane przez wallabag służące do automatycznego tagowania nowych wpisów.<br />Za każdym razem kiedy dodasz nowy wpis, zostaną użyte wszystkie skonfigurowane przez ciebie reguły. Dzięki temu unikniesz konieczności ręcznego ich klasyfikowania.
|
||||||
how_to_use_them_title: Jak ich użyć?
|
how_to_use_them_title: Jak ich użyć?
|
||||||
how_to_use_them_description: 'Załóżmy, że chcesz otagować nowe wpisy jako « <i>krótki tekst</i> » jeżeli czas czytania wynosi mniej niż 3 minuty.<br />W tym przypadku powinieneś umieścić « czasCzytania <= 3 » w polu <i>Reguła</i> i « <i>krótki tekst</i> » w polu <i>Tags</i> .<br />Wiele tagów może zostać dodanych jednocześnie rozdzielając je przecinkami: « <i>do szybkiego przeczytania, koniecznie przeczytać</i> »<br />Kompleksowe reguły mogą być napisane przy użyciu operatorów: jeżeli « <i>czasCzytania >= 5 I nazwaDomeny = "github.com"</i> » wtedy otaguj jako « <i>dłuższy tekst, GitHub </i> »'
|
how_to_use_them_description: 'Załóżmy, że chcesz otagować nowe wpisy jako « <i>krótki tekst</i> » jeżeli czas czytania wynosi mniej niż 3 minuty.<br />W tym przypadku powinieneś umieścić « czasCzytania <= 3 » w polu <i>Reguła</i> i « <i>krótki tekst</i> » w polu <i>Tags</i> .<br />Wiele tagów może zostać dodanych jednocześnie rozdzielając je przecinkami: « <i>do szybkiego przeczytania, koniecznie przeczytać</i> »<br />Kompleksowe reguły mogą być napisane przy użyciu operatorów: jeżeli « <i>czasCzytania >= 5 I nazwaDomeny = "www.php.net"</i> » wtedy otaguj jako « <i>dłuższy tekst, php</i> »'
|
||||||
variables_available_title: Jakich zmiennych i operatorów mogę użyć przy pisaniu reguł?
|
variables_available_title: Jakich zmiennych i operatorów mogę użyć przy pisaniu reguł?
|
||||||
variables_available_description: 'Następujące zmienne i operatory mogą być użyte przy tworzeniu reguł tagowania:'
|
variables_available_description: 'Następujące zmienne i operatory mogą być użyte przy tworzeniu reguł tagowania:'
|
||||||
meaning: Znaczenie
|
meaning: Znaczenie
|
||||||
|
|
|
@ -111,7 +111,7 @@ config:
|
||||||
tagging_rules_definition_title: 'O que as « regras de tags » significam?'
|
tagging_rules_definition_title: 'O que as « regras de tags » significam?'
|
||||||
tagging_rules_definition_description: 'São regras usadas pelo Wallabag para automaticamente adicionar tags em novos artigos.<br />Cada vez que um novo artigo é adicionado, todas as regras de tags podem ser usadas para adicionar as tags que você configurou, ajudando-o com o problema de classificar manualmente seus artigos.'
|
tagging_rules_definition_description: 'São regras usadas pelo Wallabag para automaticamente adicionar tags em novos artigos.<br />Cada vez que um novo artigo é adicionado, todas as regras de tags podem ser usadas para adicionar as tags que você configurou, ajudando-o com o problema de classificar manualmente seus artigos.'
|
||||||
how_to_use_them_title: 'Como eu as utilizo?'
|
how_to_use_them_title: 'Como eu as utilizo?'
|
||||||
how_to_use_them_description: 'Vamos dizer que você deseja adicionar a tag « <i>leitura rápida</i> » quando o tempo de leitura for menor que 3 minutos.<br />Neste caso, você deve « readingTime <= 3 » no campo <i>Regra</i> e « <i>leitura rápida</i> » no campo <i>Tags</i>.<br />Diversas tags podem ser adicionadas simultâneamente separando-as com vírgula: « <i>leitura rápida, precisa ser lido</i> »<br />Regras complexas podem ser escritas usando os seguintes operadores pré-definidos: if « <i>readingTime >= 5 AND domainName = "github.com"</i> » então adicione a tag « <i>leitura longa, github </i> »'
|
how_to_use_them_description: 'Vamos dizer que você deseja adicionar a tag « <i>leitura rápida</i> » quando o tempo de leitura for menor que 3 minutos.<br />Neste caso, você deve « readingTime <= 3 » no campo <i>Regra</i> e « <i>leitura rápida</i> » no campo <i>Tags</i>.<br />Diversas tags podem ser adicionadas simultâneamente separando-as com vírgula: « <i>leitura rápida, precisa ser lido</i> »<br />Regras complexas podem ser escritas usando os seguintes operadores pré-definidos: if « <i>readingTime >= 5 AND domainName = "www.php.net"</i> » então adicione a tag « <i>leitura longa, php</i> »'
|
||||||
variables_available_title: 'Quais variáveis e operadores eu posso usar para escrever regras?'
|
variables_available_title: 'Quais variáveis e operadores eu posso usar para escrever regras?'
|
||||||
variables_available_description: 'As seguintes variáveis e operadores podem ser usados para criar regras de tags:'
|
variables_available_description: 'As seguintes variáveis e operadores podem ser usados para criar regras de tags:'
|
||||||
meaning: ''
|
meaning: ''
|
||||||
|
|
|
@ -150,7 +150,7 @@ config:
|
||||||
tagging_rules_definition_title: 'Что значит "правила тегирования"?'
|
tagging_rules_definition_title: 'Что значит "правила тегирования"?'
|
||||||
tagging_rules_definition_description: 'Правила, по которым wallabag автоматически добавит теги для новых записей.<br />Каждый раз, при добавлении новых записей, будут проставляться теги к записям, согласно настроенным правилам тегирования, это избавит Вас от необходимости проставлять теги для каждой записи вручную.'
|
tagging_rules_definition_description: 'Правила, по которым wallabag автоматически добавит теги для новых записей.<br />Каждый раз, при добавлении новых записей, будут проставляться теги к записям, согласно настроенным правилам тегирования, это избавит Вас от необходимости проставлять теги для каждой записи вручную.'
|
||||||
how_to_use_them_title: 'Как мне их использовать?'
|
how_to_use_them_title: 'Как мне их использовать?'
|
||||||
how_to_use_them_description: 'Предположим, вы хотите пометить новые записи как "<i>короткая</i>", когда на чтение уйдет меньше 3 минут.<br />В этом случае, установите " readingTime <= 3 " в поле <i>Правила</i> и "<i>короткая</i>" в поле <i>Теги</i>.<br />Несколько тегов могут добавляться одновременно, разделяя их запятой: "<i>короткая, прочитать обязательно</i>" <br />Сложные правила могут быть записаны с использованием предопределенных операторов: если "<i>readingTime >= 5 AND domainName = \"github.com\"</i> " тогда тег будет "<i>долго читать, GitHub </i>"'
|
how_to_use_them_description: 'Предположим, вы хотите пометить новые записи как "<i>короткая</i>", когда на чтение уйдет меньше 3 минут.<br />В этом случае, установите " readingTime <= 3 " в поле <i>Правила</i> и "<i>короткая</i>" в поле <i>Теги</i>.<br />Несколько тегов могут добавляться одновременно, разделяя их запятой: "<i>короткая, прочитать обязательно</i>" <br />Сложные правила могут быть записаны с использованием предопределенных операторов: если "<i>readingTime >= 5 AND domainName = \"www.php.net\"</i> " тогда тег будет "<i>долго читать, php</i>"'
|
||||||
variables_available_title: 'Какие переменные и операторы я могу использовать для написания правил?'
|
variables_available_title: 'Какие переменные и операторы я могу использовать для написания правил?'
|
||||||
variables_available_description: 'Следующие переменные и операторы могут использоваться для создания правил тегов:'
|
variables_available_description: 'Следующие переменные и операторы могут использоваться для создания правил тегов:'
|
||||||
meaning: 'Смысл'
|
meaning: 'Смысл'
|
||||||
|
|
|
@ -124,7 +124,7 @@ config:
|
||||||
tagging_rules_definition_title: 'ข้อบังคับการแท็กคืออะไร?'
|
tagging_rules_definition_title: 'ข้อบังคับการแท็กคืออะไร?'
|
||||||
tagging_rules_definition_description: 'การใช้ข้อบังคับโดย Wallabag ไปแท็กรายการใหม่อัตโนมัติ <br />แต่ละช่วงรายการใหม่จะเป็นการเพิ่ม, การแท็กข้อบังคับทั้งหมดจะใช้การเพิ่มแท็กที่คุณกำหนดค่า, ดังนั้นการบันทึกของคุณจะเป็นปัญหาในการจัดหมวดหมู่ของรายการของคุณ'
|
tagging_rules_definition_description: 'การใช้ข้อบังคับโดย Wallabag ไปแท็กรายการใหม่อัตโนมัติ <br />แต่ละช่วงรายการใหม่จะเป็นการเพิ่ม, การแท็กข้อบังคับทั้งหมดจะใช้การเพิ่มแท็กที่คุณกำหนดค่า, ดังนั้นการบันทึกของคุณจะเป็นปัญหาในการจัดหมวดหมู่ของรายการของคุณ'
|
||||||
how_to_use_them_title: 'ฉันจะใช้ได้อย่างไร?'
|
how_to_use_them_title: 'ฉันจะใช้ได้อย่างไร?'
|
||||||
how_to_use_them_description: 'การสมมติที่คุณต้องการแท็กรายการใหม่ไปยัง « <i>การอ่านแบบสั้น</i> » เมื่ออ่านในช่วง 3 นาที <br />ในกรณีนี้, คุณควรใส่ « readingTime <= 3 » ภายใน <i>ข้อบังคับ</i> ของพื่นที่และ « <i>การอ่านแบบสั้น</i> » ภายใน <i>แท็ก</i> ของพื้นที่<br />ในหลายแท็กสามารถเพิ่มได้พร้อมกันโดยแบ่งกับ comma: « <i>การอ่านแบบสั้น, ต้องอ่าน</i> »<br />ข้อบังคับที่ซับซ้อนสามารถเขียนโดยการใช้การดำเนินการที่กำหนดไว้ก่อน: ถ้า « <i>readingTime >= 5 AND domainName = "github.com"</i> » ดังนั้นแท็กไปยัง « <i>การอ่านแบบยาว, github </i> »'
|
how_to_use_them_description: 'การสมมติที่คุณต้องการแท็กรายการใหม่ไปยัง « <i>การอ่านแบบสั้น</i> » เมื่ออ่านในช่วง 3 นาที <br />ในกรณีนี้, คุณควรใส่ « readingTime <= 3 » ภายใน <i>ข้อบังคับ</i> ของพื่นที่และ « <i>การอ่านแบบสั้น</i> » ภายใน <i>แท็ก</i> ของพื้นที่<br />ในหลายแท็กสามารถเพิ่มได้พร้อมกันโดยแบ่งกับ comma: « <i>การอ่านแบบสั้น, ต้องอ่าน</i> »<br />ข้อบังคับที่ซับซ้อนสามารถเขียนโดยการใช้การดำเนินการที่กำหนดไว้ก่อน: ถ้า « <i>readingTime >= 5 AND domainName = "www.php.net"</i> » ดังนั้นแท็กไปยัง « <i>การอ่านแบบยาว, php</i> »'
|
||||||
variables_available_title: 'ตัวแปรและตัวดำเนินการสามารถให้ใช้การเขียนข้อบังคับได้ที่ไหน?'
|
variables_available_title: 'ตัวแปรและตัวดำเนินการสามารถให้ใช้การเขียนข้อบังคับได้ที่ไหน?'
|
||||||
variables_available_description: 'การติดตามตัวแปรและตัวดำเนินการสามารถใช้การสร้างข้อบังคับแท็ก:'
|
variables_available_description: 'การติดตามตัวแปรและตัวดำเนินการสามารถใช้การสร้างข้อบังคับแท็ก:'
|
||||||
meaning: 'ความหมาย'
|
meaning: 'ความหมาย'
|
||||||
|
|
|
@ -164,7 +164,7 @@ config:
|
||||||
matches: '<i>konu</i>nun <i>arama</i> kriterine (büyük küçük harf duyarsız) eşleştiğini test eder.<br />Örnek: <code>title matches "futbol"</code>'
|
matches: '<i>konu</i>nun <i>arama</i> kriterine (büyük küçük harf duyarsız) eşleştiğini test eder.<br />Örnek: <code>title matches "futbol"</code>'
|
||||||
notmatches: '<i>konu</i>nun <i>arama</i> kriterine (büyük küçük harf duyarsız) eşleşmediğini test eder.<br />Örnek: <code>title nonmatches "futbol"</code>'
|
notmatches: '<i>konu</i>nun <i>arama</i> kriterine (büyük küçük harf duyarsız) eşleşmediğini test eder.<br />Örnek: <code>title nonmatches "futbol"</code>'
|
||||||
tagging_rules_definition_description: Bunlar wallabag'in yeni makaleleri otomatik olarak etiketleyebilmesi için tanımlanmış kurallardır.<br />Her yeni makale eklendiğinde, ayarladığınız tüm etiket kuralları kullanılarak makaleniz etiketlenecektir. Bu sayede her bir makaleyi tek tek etiketlemekle uğraşmanız gerekmeyecek.
|
tagging_rules_definition_description: Bunlar wallabag'in yeni makaleleri otomatik olarak etiketleyebilmesi için tanımlanmış kurallardır.<br />Her yeni makale eklendiğinde, ayarladığınız tüm etiket kuralları kullanılarak makaleniz etiketlenecektir. Bu sayede her bir makaleyi tek tek etiketlemekle uğraşmanız gerekmeyecek.
|
||||||
how_to_use_them_description: 'Örneğin, 3 dakikadan kısa okuma süresi olan yeni makaleleri « <i>kısa okumalar</i>» etiketi ile etiketlemek istiyorsunuz diyelim.<br />Bu durumda, <i>Kural</i> alanına « readingTime < = 3 » değeri, ve de <i>Etiketler</i> alanına da <i>kısa okumalar</i> değerini girmelisiniz.<br /> Eğer birden fazla etiket tanımlamak istiyorsanız arasına virgül koyabilirsiniz: « <i>kısa okumalar, mutlaka oku</i> »<br />Daha kompleks kurallar önden tanımlanmış operatörlerle girilebilir: Eğer « <i> readingTime > = AND domainName = "github.com"</i> » ise, o zaman « <i>uzun okumalar, GitHub</i> » gibi girebilirsiniz'
|
how_to_use_them_description: 'Örneğin, 3 dakikadan kısa okuma süresi olan yeni makaleleri « <i>kısa okumalar</i>» etiketi ile etiketlemek istiyorsunuz diyelim.<br />Bu durumda, <i>Kural</i> alanına « readingTime < = 3 » değeri, ve de <i>Etiketler</i> alanına da <i>kısa okumalar</i> değerini girmelisiniz.<br /> Eğer birden fazla etiket tanımlamak istiyorsanız arasına virgül koyabilirsiniz: « <i>kısa okumalar, mutlaka oku</i> »<br />Daha kompleks kurallar önden tanımlanmış operatörlerle girilebilir: Eğer « <i> readingTime > = AND domainName = "www.php.net"</i> » ise, o zaman « <i>uzun okumalar, php</i> » gibi girebilirsiniz'
|
||||||
if_label: eğer
|
if_label: eğer
|
||||||
then_tag_as_label: ise, şu şekilde etiketle
|
then_tag_as_label: ise, şu şekilde etiketle
|
||||||
delete_rule_label: sil
|
delete_rule_label: sil
|
||||||
|
|
|
@ -160,7 +160,7 @@ config:
|
||||||
tagging_rules_definition_title: '“标签规则”是什么意思?'
|
tagging_rules_definition_title: '“标签规则”是什么意思?'
|
||||||
tagging_rules_definition_description: '它们是 wallabag 用来给新项目自动打上标签的规则。<br />每当一个新项目被添加进来,所有标签规则都会作用于这个项目,为它打上你配置好的标签,免去你手动分类的麻烦。'
|
tagging_rules_definition_description: '它们是 wallabag 用来给新项目自动打上标签的规则。<br />每当一个新项目被添加进来,所有标签规则都会作用于这个项目,为它打上你配置好的标签,免去你手动分类的麻烦。'
|
||||||
how_to_use_them_title: '我该怎么使用它们?'
|
how_to_use_them_title: '我该怎么使用它们?'
|
||||||
how_to_use_them_description: '假设你想要将一个阅读时间短于 3 分钟的新项目标记为“ <i>短阅读</i> ”。<br /> 你应该在 <i>规则</i> 区域输入“readingTime <= 3”,并在 <i>标签</i> 区域输入“<i>短阅读</i>”。<br /> 可以同时添加数个标签,只需要用半角逗号来隔开它们,如:“<i>短阅读, 必读</i>”<br /> 可以使用预定义的操作符来编写复杂的规则,如:如果“ <i>readingTime >= 5 AND domainName ="github.com"</i>”则标记为“<i>长阅读, github</i>”'
|
how_to_use_them_description: '假设你想要将一个阅读时间短于 3 分钟的新项目标记为“ <i>短阅读</i> ”。<br /> 你应该在 <i>规则</i> 区域输入“readingTime <= 3”,并在 <i>标签</i> 区域输入“<i>短阅读</i>”。<br /> 可以同时添加数个标签,只需要用半角逗号来隔开它们,如:“<i>短阅读, 必读</i>”<br /> 可以使用预定义的操作符来编写复杂的规则,如:如果“ <i>readingTime >= 5 AND domainName ="www.php.net"</i>”则标记为“<i>长阅读, php</i>”'
|
||||||
variables_available_title: '我可以使用哪些变量和操作符来编写规则?'
|
variables_available_title: '我可以使用哪些变量和操作符来编写规则?'
|
||||||
variables_available_description: '可以使用以下变量和操作符来编写标签规则:'
|
variables_available_description: '可以使用以下变量和操作符来编写标签规则:'
|
||||||
meaning: '含义'
|
meaning: '含义'
|
||||||
|
@ -253,6 +253,7 @@ entry:
|
||||||
toogle_as_star: '添加到收藏'
|
toogle_as_star: '添加到收藏'
|
||||||
delete: '删除'
|
delete: '删除'
|
||||||
export_title: '导出'
|
export_title: '导出'
|
||||||
|
assign_search_tag: 将此搜索作为标签分配给每个结果
|
||||||
filters:
|
filters:
|
||||||
title: '筛选器'
|
title: '筛选器'
|
||||||
status_label: '状态'
|
status_label: '状态'
|
||||||
|
|
|
@ -57,6 +57,11 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block messages %}
|
{% block messages %}
|
||||||
|
<div style="margin-top: 10px; color: #e01a15; border-left: 20px #e01a15 solid; padding-left: 10px; border-bottom: 6px #e01a15 solid; border-bottom-left-radius: 10px;">
|
||||||
|
<h3>⚠️ You are using the Baggy theme which is now deprecated.</h3>
|
||||||
|
<p>It will be removed in the next version. You can use the Material theme by <a href="{{ path('config') }}">updating the theme config</a>.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% for flashMessage in app.session.flashbag.get('notice') %}
|
{% for flashMessage in app.session.flashbag.get('notice') %}
|
||||||
<div class="messages success">
|
<div class="messages success">
|
||||||
<a href="#" class="closeMessage">×</a>
|
<a href="#" class="closeMessage">×</a>
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
<title>wallabag — {{type}} {{ tag }} feed</title>
|
<title>wallabag — {{type}} {{ tag }} feed</title>
|
||||||
<subtitle type="html">Atom feed for entries tagged with {{ tag }}</subtitle>
|
<subtitle type="html">Atom feed for entries tagged with {{ tag }}</subtitle>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if entries | length > 0 %}
|
{% if updated %}
|
||||||
<updated>{{ (entries | first).createdAt | date('c') }}</updated> {# Indicates the last time the feed was modified in a significant way. #}
|
<updated>{{ updated | date('c') }}</updated> {# Indicates the last time the feed was modified in a significant way. #}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<link rel="self" type="application/atom+xml" href="{{ app.request.uri }}"/>
|
<link rel="self" type="application/atom+xml" href="{{ app.request.uri }}"/>
|
||||||
{% if entries.hasPreviousPage %}
|
{% if entries.hasPreviousPage %}
|
||||||
|
|
|
@ -9,10 +9,16 @@
|
||||||
|
|
||||||
<ul class="tools right">
|
<ul class="tools right">
|
||||||
<li>
|
<li>
|
||||||
<a title="{{ 'entry.list.show_same_domain'|trans }}" class="tool grey-text" href="{{ path('same_domain', { 'id': entry.id }) }}"><i class="material-icons">language</i></a>
|
<a title="{{ 'entry.list.show_same_domain'|trans }}" class="tool grey-text" href="{{ path('same_domain', { 'id': entry.id }) }}" data-action="same_domain" data-entry-id="{{ entry.id }}"><i class="material-icons">language</i></a>
|
||||||
<a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool grey-text" href="{{ path('archive_entry', { 'id': entry.id }) }}"><i class="material-icons">{% if entry.isArchived == 0 %}done{% else %}unarchive{% endif %}</i></a>
|
</li>
|
||||||
<a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool grey-text" href="{{ path('star_entry', { 'id': entry.id }) }}"><i class="material-icons">{% if entry.isStarred == 0 %}star_border{% else %}star{% endif %}</i></a>
|
<li>
|
||||||
<a title="{{ 'entry.list.delete'|trans }}" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" class="tool grey-text delete" href="{{ path('delete_entry', { 'id': entry.id }) }}"><i class="material-icons">delete</i></a>
|
<a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool grey-text" href="{{ path('archive_entry', { 'id': entry.id }) }}" data-action="archived" data-entry-id="{{ entry.id }}"><i class="material-icons">{% if entry.isArchived == 0 %}done{% else %}unarchive{% endif %}</i></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool grey-text" href="{{ path('star_entry', { 'id': entry.id }) }}" data-action="star" data-entry-id="{{ entry.id }}"><i class="material-icons">{% if entry.isStarred == 0 %}star_border{% else %}star{% endif %}</i></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a title="{{ 'entry.list.delete'|trans }}" data-action-confirm="{{ 'entry.confirm.delete'|trans }}" class="tool grey-text delete" href="{{ path('delete_entry', { 'id': entry.id }) }}" data-action="delete" data-entry-id="{{ entry.id }}"><i class="material-icons">delete</i></a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="card{% if currentRoute in routes and entry.isArchived %} archived{% endif %}">
|
<div class="card entry-card{% if currentRoute in routes and entry.isArchived %} archived{% endif %}">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="card-fullimage">
|
<div class="card-fullimage">
|
||||||
<ul class="card-entry-labels">
|
<ul class="card-entry-labels">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="card{% if currentRoute in routes and entry.isArchived %} archived{% endif %}">
|
<div class="card entry-card{% if currentRoute in routes and entry.isArchived %} archived{% endif %}">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="card-image waves-effect waves-block waves-light">
|
<div class="card-image waves-effect waves-block waves-light">
|
||||||
<ul class="card-entry-labels">
|
<ul class="card-entry-labels">
|
||||||
|
|
|
@ -34,14 +34,14 @@
|
||||||
{% include "@WallabagCore/themes/common/Entry/_feed_link.html.twig" %}
|
{% include "@WallabagCore/themes/common/Entry/_feed_link.html.twig" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
{% if currentRoute == 'search' %}<div><a href="{{ path('tag_this_search', {'filter': searchTerm, 'currentRoute': app.request.get('currentRoute') }) }}" title="{{ 'entry.list.assign_search_tag'|trans }}">{{ 'entry.list.assign_search_tag'|trans }}</a></div>{% endif %}
|
||||||
{% if entries.getNbPages > 1 %}
|
{% if entries.getNbPages > 1 %}
|
||||||
{{ pagerfanta(entries, 'twitter_bootstrap_translated', {'proximity': 1}) }}
|
{{ pagerfanta(entries, 'twitter_bootstrap_translated', {'proximity': 1}) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul class="{% if listMode == 1 %}collection{% else %}row data{% endif %}">
|
{% if listMode == 1 %}
|
||||||
|
<div class="mass-buttons">
|
||||||
<li class="mass-buttons">
|
|
||||||
{% if entries.count > 0 and listMode == 1 %}
|
{% if entries.count > 0 and listMode == 1 %}
|
||||||
<span>
|
<span>
|
||||||
<input id="selectAll" type="checkbox" data-toggle="[data-js='entry-checkbox']" data-js="checkboxes-toggle" />
|
<input id="selectAll" type="checkbox" data-toggle="[data-js='entry-checkbox']" data-js="checkboxes-toggle" />
|
||||||
|
@ -53,10 +53,13 @@
|
||||||
<button class="btn cyan darken-1" type="submit" name="delete" onclick="return confirm('{{ 'entry.confirm.delete_entries'|trans|escape('js') }}')" title="{{ 'entry.list.delete'|trans }}"><i class="material-icons">delete</i></button>
|
<button class="btn cyan darken-1" type="submit" name="delete" onclick="return confirm('{{ 'entry.confirm.delete_entries'|trans|escape('js') }}')" title="{{ 'entry.list.delete'|trans }}"><i class="material-icons">delete</i></button>
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<ol class="entries {% if listMode == 1 %}collection{% else %}row entries-row data{% endif %}">
|
||||||
|
|
||||||
{% for entry in entries %}
|
{% for entry in entries %}
|
||||||
<li id="entry-{{ entry.id|e }}" class="entry col {% if listMode == 0 %}l3 m6{% else %}collection-item{% endif %} s12">
|
<li id="entry-{{ entry.id|e }}" class="{% if listMode != 0 %}col collection-item{% endif %} s12" data-entry-id="{{ entry.id|e }}" data-test="entry">
|
||||||
{% if listMode == 1 %}
|
{% if listMode == 1 %}
|
||||||
{% include "@WallabagCore/themes/material/Entry/_card_list.html.twig" with {'entry': entry, 'currentRoute': currentRoute, 'routes': entriesWithArchivedClassRoutes} only %}
|
{% include "@WallabagCore/themes/material/Entry/_card_list.html.twig" with {'entry': entry, 'currentRoute': currentRoute, 'routes': entriesWithArchivedClassRoutes} only %}
|
||||||
{% elseif not entry.previewPicture is null and entry.mimetype starts with 'image/' %}
|
{% elseif not entry.previewPicture is null and entry.mimetype starts with 'image/' %}
|
||||||
|
@ -66,7 +69,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ol>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% if entries.getNbPages > 1 %}
|
{% if entries.getNbPages > 1 %}
|
||||||
|
|
|
@ -6,8 +6,4 @@ use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||||
|
|
||||||
class WallabagUserBundle extends Bundle
|
class WallabagUserBundle extends Bundle
|
||||||
{
|
{
|
||||||
public function getParent()
|
|
||||||
{
|
|
||||||
return 'FOSUserBundle';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Wallabag\ApiBundle\Controller;
|
||||||
|
|
||||||
|
use Tests\Wallabag\ApiBundle\WallabagApiTestCase;
|
||||||
|
|
||||||
|
class ConfigRestControllerTest extends WallabagApiTestCase
|
||||||
|
{
|
||||||
|
public function testGetConfig()
|
||||||
|
{
|
||||||
|
$this->client->request('GET', '/api/config.json');
|
||||||
|
$this->assertSame(200, $this->client->getResponse()->getStatusCode());
|
||||||
|
|
||||||
|
$config = json_decode($this->client->getResponse()->getContent(), true);
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('id', $config);
|
||||||
|
$this->assertArrayHasKey('items_per_page', $config);
|
||||||
|
$this->assertArrayHasKey('language', $config);
|
||||||
|
$this->assertArrayHasKey('reading_speed', $config);
|
||||||
|
$this->assertArrayHasKey('action_mark_as_read', $config);
|
||||||
|
$this->assertArrayHasKey('list_mode', $config);
|
||||||
|
|
||||||
|
$this->assertSame(200.0, $config['reading_speed']);
|
||||||
|
$this->assertSame('en', $config['language']);
|
||||||
|
|
||||||
|
$this->assertCount(6, $config);
|
||||||
|
|
||||||
|
$this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetConfigWithoutAuthentication()
|
||||||
|
{
|
||||||
|
$client = static::createClient();
|
||||||
|
$client->request('GET', '/api/config.json');
|
||||||
|
$this->assertSame(401, $client->getResponse()->getStatusCode());
|
||||||
|
|
||||||
|
$config = json_decode($client->getResponse()->getContent(), true);
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('error', $config);
|
||||||
|
$this->assertArrayHasKey('error_description', $config);
|
||||||
|
|
||||||
|
$this->assertSame('access_denied', $config['error']);
|
||||||
|
|
||||||
|
$this->assertSame('application/json', $client->getResponse()->headers->get('Content-Type'));
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
const AN_URL_CONTAINING_AN_ARTICLE_WITH_IMAGE = 'https://www.lemonde.fr/judo/article/2017/11/11/judo-la-decima-de-teddy-riner_5213605_1556020.html';
|
const AN_URL_CONTAINING_AN_ARTICLE_WITH_IMAGE = 'https://www.lemonde.fr/judo/article/2017/11/11/judo-la-decima-de-teddy-riner_5213605_1556020.html';
|
||||||
public $downloadImagesEnabled = false;
|
public $downloadImagesEnabled = false;
|
||||||
public $url = 'https://www.lemonde.fr/pixels/article/2019/06/18/ce-qu-il-faut-savoir-sur-le-libra-la-cryptomonnaie-de-facebook_5477887_4408996.html';
|
public $url = 'https://www.lemonde.fr/pixels/article/2019/06/18/ce-qu-il-faut-savoir-sur-le-libra-la-cryptomonnaie-de-facebook_5477887_4408996.html';
|
||||||
|
private $entryDataTestAttribute = '[data-test="entry"]';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @after
|
* @after
|
||||||
|
@ -101,14 +102,14 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->request('GET', '/');
|
$crawler = $client->request('GET', '/');
|
||||||
|
|
||||||
$this->assertCount(4, $crawler->filter('li.entry'));
|
$this->assertCount(4, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
// Good URL
|
// Good URL
|
||||||
$client->request('GET', '/bookmarklet', ['url' => $this->url]);
|
$client->request('GET', '/bookmarklet', ['url' => $this->url]);
|
||||||
$this->assertSame(302, $client->getResponse()->getStatusCode());
|
$this->assertSame(302, $client->getResponse()->getStatusCode());
|
||||||
$client->followRedirect();
|
$client->followRedirect();
|
||||||
$crawler = $client->request('GET', '/');
|
$crawler = $client->request('GET', '/');
|
||||||
$this->assertCount(5, $crawler->filter('li.entry'));
|
$this->assertCount(5, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
$em = $client->getContainer()
|
$em = $client->getContainer()
|
||||||
->get('doctrine.orm.entity_manager');
|
->get('doctrine.orm.entity_manager');
|
||||||
|
@ -176,6 +177,42 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
$client->getContainer()->get('craue_config')->set('store_article_headers', 0);
|
$client->getContainer()->get('craue_config')->set('store_article_headers', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group NetworkCalls
|
||||||
|
*/
|
||||||
|
public function testPostNewOkWithTaggingRules()
|
||||||
|
{
|
||||||
|
$this->logInAs('empty');
|
||||||
|
$client = $this->getClient();
|
||||||
|
|
||||||
|
$crawler = $client->request('GET', '/new');
|
||||||
|
|
||||||
|
$this->assertSame(200, $client->getResponse()->getStatusCode());
|
||||||
|
|
||||||
|
$form = $crawler->filter('form[name=entry]')->form();
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'entry[url]' => $this->url,
|
||||||
|
];
|
||||||
|
|
||||||
|
$client->submit($form, $data);
|
||||||
|
|
||||||
|
$this->assertSame(302, $client->getResponse()->getStatusCode());
|
||||||
|
|
||||||
|
$content = $client->getContainer()
|
||||||
|
->get('doctrine.orm.entity_manager')
|
||||||
|
->getRepository('WallabagCoreBundle:Entry')
|
||||||
|
->findByUrlAndUserId($this->url, $this->getLoggedInUserId());
|
||||||
|
|
||||||
|
$tags = $content->getTagsLabel();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Without the custom reading speed of `empty` user, it'll be inversed
|
||||||
|
*/
|
||||||
|
$this->assertContains('longread', $tags);
|
||||||
|
$this->assertNotContains('shortread', $tags);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group NetworkCalls
|
* @group NetworkCalls
|
||||||
*/
|
*/
|
||||||
|
@ -734,7 +771,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
$this->assertCount(1, $crawler->filter('li.entry'));
|
$this->assertCount(1, $crawler->filter($this->entryDataTestAttribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFilterOnReadingTimeWithNegativeValue()
|
public function testFilterOnReadingTimeWithNegativeValue()
|
||||||
|
@ -754,7 +791,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
// forcing negative value results in no entry displayed
|
// forcing negative value results in no entry displayed
|
||||||
$this->assertCount(0, $crawler->filter('li.entry'));
|
$this->assertCount(0, $crawler->filter($this->entryDataTestAttribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFilterOnReadingTimeOnlyUpper()
|
public function testFilterOnReadingTimeOnlyUpper()
|
||||||
|
@ -763,7 +800,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
$client = $this->getClient();
|
$client = $this->getClient();
|
||||||
|
|
||||||
$crawler = $client->request('GET', '/all/list');
|
$crawler = $client->request('GET', '/all/list');
|
||||||
$this->assertCount(5, $crawler->filter('li.entry'));
|
$this->assertCount(5, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
$entry = new Entry($this->getLoggedInUser());
|
$entry = new Entry($this->getLoggedInUser());
|
||||||
$entry->setUrl($this->url);
|
$entry->setUrl($this->url);
|
||||||
|
@ -772,7 +809,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
$this->getEntityManager()->flush();
|
$this->getEntityManager()->flush();
|
||||||
|
|
||||||
$crawler = $client->request('GET', '/all/list');
|
$crawler = $client->request('GET', '/all/list');
|
||||||
$this->assertCount(6, $crawler->filter('li.entry'));
|
$this->assertCount(6, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
$form = $crawler->filter('button[id=submit-filter]')->form();
|
$form = $crawler->filter('button[id=submit-filter]')->form();
|
||||||
|
|
||||||
|
@ -782,7 +819,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
$this->assertCount(5, $crawler->filter('li.entry'));
|
$this->assertCount(5, $crawler->filter($this->entryDataTestAttribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFilterOnReadingTimeOnlyLower()
|
public function testFilterOnReadingTimeOnlyLower()
|
||||||
|
@ -800,7 +837,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
$this->assertCount(0, $crawler->filter('li.entry'));
|
$this->assertCount(0, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
$entry = new Entry($this->getLoggedInUser());
|
$entry = new Entry($this->getLoggedInUser());
|
||||||
$entry->setUrl($this->url);
|
$entry->setUrl($this->url);
|
||||||
|
@ -809,7 +846,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
$this->getEntityManager()->flush();
|
$this->getEntityManager()->flush();
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
$this->assertCount(1, $crawler->filter('li.entry'));
|
$this->assertCount(1, $crawler->filter($this->entryDataTestAttribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFilterOnUnreadStatus()
|
public function testFilterOnUnreadStatus()
|
||||||
|
@ -827,7 +864,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
$this->assertCount(4, $crawler->filter('li.entry'));
|
$this->assertCount(4, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
$entry = new Entry($this->getLoggedInUser());
|
$entry = new Entry($this->getLoggedInUser());
|
||||||
$entry->setUrl($this->url);
|
$entry->setUrl($this->url);
|
||||||
|
@ -837,7 +874,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
$this->assertCount(5, $crawler->filter('li.entry'));
|
$this->assertCount(5, $crawler->filter($this->entryDataTestAttribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFilterOnCreationDate()
|
public function testFilterOnCreationDate()
|
||||||
|
@ -868,7 +905,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
$this->assertCount(4, $crawler->filter('li.entry'));
|
$this->assertCount(4, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'entry_filter[createdAt][left_date]' => $today->format('Y-m-d'),
|
'entry_filter[createdAt][left_date]' => $today->format('Y-m-d'),
|
||||||
|
@ -877,7 +914,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
$this->assertCount(4, $crawler->filter('li.entry'));
|
$this->assertCount(4, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'entry_filter[createdAt][left_date]' => '1970-01-01',
|
'entry_filter[createdAt][left_date]' => '1970-01-01',
|
||||||
|
@ -886,7 +923,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
$this->assertCount(0, $crawler->filter('li.entry'));
|
$this->assertCount(0, $crawler->filter($this->entryDataTestAttribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFilterOnAnnotatedStatus()
|
public function testFilterOnAnnotatedStatus()
|
||||||
|
@ -968,7 +1005,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
];
|
];
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
$this->assertCount(4, $crawler->filter('li.entry'));
|
$this->assertCount(4, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
$crawler = $client->request('GET', '/unread/list');
|
$crawler = $client->request('GET', '/unread/list');
|
||||||
$form = $crawler->filter('button[id=submit-filter]')->form();
|
$form = $crawler->filter('button[id=submit-filter]')->form();
|
||||||
|
@ -977,7 +1014,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
];
|
];
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
$this->assertCount(4, $crawler->filter('li.entry'));
|
$this->assertCount(4, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
$form = $crawler->filter('button[id=submit-filter]')->form();
|
$form = $crawler->filter('button[id=submit-filter]')->form();
|
||||||
$data = [
|
$data = [
|
||||||
|
@ -985,7 +1022,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
];
|
];
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
$this->assertCount(0, $crawler->filter('li.entry'));
|
$this->assertCount(0, $crawler->filter($this->entryDataTestAttribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFilterOnStatus()
|
public function testFilterOnStatus()
|
||||||
|
@ -1000,14 +1037,14 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
$form['entry_filter[isUnread]']->untick();
|
$form['entry_filter[isUnread]']->untick();
|
||||||
|
|
||||||
$crawler = $client->submit($form);
|
$crawler = $client->submit($form);
|
||||||
$this->assertCount(1, $crawler->filter('li.entry'));
|
$this->assertCount(1, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
$form = $crawler->filter('button[id=submit-filter]')->form();
|
$form = $crawler->filter('button[id=submit-filter]')->form();
|
||||||
$form['entry_filter[isArchived]']->untick();
|
$form['entry_filter[isArchived]']->untick();
|
||||||
$form['entry_filter[isStarred]']->tick();
|
$form['entry_filter[isStarred]']->tick();
|
||||||
|
|
||||||
$crawler = $client->submit($form);
|
$crawler = $client->submit($form);
|
||||||
$this->assertCount(1, $crawler->filter('li.entry'));
|
$this->assertCount(1, $crawler->filter($this->entryDataTestAttribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFilterPreselectedStatus()
|
public function testFilterPreselectedStatus()
|
||||||
|
@ -1044,7 +1081,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
$form['entry_filter[isPublic]']->tick();
|
$form['entry_filter[isPublic]']->tick();
|
||||||
|
|
||||||
$crawler = $client->submit($form);
|
$crawler = $client->submit($form);
|
||||||
$this->assertCount(0, $crawler->filter('li.entry'));
|
$this->assertCount(0, $crawler->filter($this->entryDataTestAttribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPreviewPictureFilter()
|
public function testPreviewPictureFilter()
|
||||||
|
@ -1057,7 +1094,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
$form['entry_filter[previewPicture]']->tick();
|
$form['entry_filter[previewPicture]']->tick();
|
||||||
|
|
||||||
$crawler = $client->submit($form);
|
$crawler = $client->submit($form);
|
||||||
$this->assertCount(1, $crawler->filter('li.entry'));
|
$this->assertCount(1, $crawler->filter($this->entryDataTestAttribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFilterOnLanguage()
|
public function testFilterOnLanguage()
|
||||||
|
@ -1078,7 +1115,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
];
|
];
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
$this->assertCount(3, $crawler->filter('li.entry'));
|
$this->assertCount(3, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
$form = $crawler->filter('button[id=submit-filter]')->form();
|
$form = $crawler->filter('button[id=submit-filter]')->form();
|
||||||
$data = [
|
$data = [
|
||||||
|
@ -1086,7 +1123,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
];
|
];
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
$this->assertCount(2, $crawler->filter('li.entry'));
|
$this->assertCount(2, $crawler->filter($this->entryDataTestAttribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testShareEntryPublicly()
|
public function testShareEntryPublicly()
|
||||||
|
@ -1289,7 +1326,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
$this->assertCount(1, $crawler->filter('li.entry'));
|
$this->assertCount(1, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
$entry = new Entry($this->getLoggedInUser());
|
$entry = new Entry($this->getLoggedInUser());
|
||||||
$entry->setUrl($this->url);
|
$entry->setUrl($this->url);
|
||||||
|
@ -1312,7 +1349,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
$this->assertCount(2, $crawler->filter('li.entry'));
|
$this->assertCount(2, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
$crawler = $client->request('GET', '/all/list');
|
$crawler = $client->request('GET', '/all/list');
|
||||||
$form = $crawler->filter('button[id=submit-filter]')->form();
|
$form = $crawler->filter('button[id=submit-filter]')->form();
|
||||||
|
@ -1323,7 +1360,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
$this->assertCount(8, $crawler->filter('li.entry'));
|
$this->assertCount(8, $crawler->filter($this->entryDataTestAttribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSearch()
|
public function testSearch()
|
||||||
|
@ -1347,7 +1384,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
$this->assertCount(4, $crawler->filter('li.entry'));
|
$this->assertCount(4, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
// Search on starred list
|
// Search on starred list
|
||||||
$crawler = $client->request('GET', '/starred/list');
|
$crawler = $client->request('GET', '/starred/list');
|
||||||
|
@ -1366,7 +1403,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
$this->assertCount(1, $crawler->filter('li.entry'));
|
$this->assertCount(1, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
$crawler = $client->request('GET', '/archive/list');
|
$crawler = $client->request('GET', '/archive/list');
|
||||||
|
|
||||||
|
@ -1385,7 +1422,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
$this->assertCount(1, $crawler->filter('li.entry'));
|
$this->assertCount(1, $crawler->filter($this->entryDataTestAttribute));
|
||||||
$client->request('GET', '/delete/' . $entry->getId());
|
$client->request('GET', '/delete/' . $entry->getId());
|
||||||
|
|
||||||
// test on list of all articles
|
// test on list of all articles
|
||||||
|
@ -1398,7 +1435,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
$this->assertCount(0, $crawler->filter('li.entry'));
|
$this->assertCount(0, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
// test url search on list of all articles
|
// test url search on list of all articles
|
||||||
$entry = new Entry($this->getLoggedInUser());
|
$entry = new Entry($this->getLoggedInUser());
|
||||||
|
@ -1417,7 +1454,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
$this->assertCount(1, $crawler->filter('li.entry'));
|
$this->assertCount(1, $crawler->filter($this->entryDataTestAttribute));
|
||||||
|
|
||||||
// same as previous test but for case-sensitivity
|
// same as previous test but for case-sensitivity
|
||||||
$crawler = $client->request('GET', '/all/list');
|
$crawler = $client->request('GET', '/all/list');
|
||||||
|
@ -1429,7 +1466,7 @@ class EntryControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$crawler = $client->submit($form, $data);
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
$this->assertCount(1, $crawler->filter('li.entry'));
|
$this->assertCount(1, $crawler->filter($this->entryDataTestAttribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function dataForLanguage()
|
public function dataForLanguage()
|
||||||
|
|
|
@ -347,6 +347,8 @@ class ExportControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
private function getSanitizedFilename($title)
|
private function getSanitizedFilename($title)
|
||||||
{
|
{
|
||||||
return preg_replace('/[^A-Za-z0-9\- \']/', '', iconv('utf-8', 'us-ascii//TRANSLIT', $title));
|
$transliterator = \Transliterator::createFromRules(':: Any-Latin; :: Latin-ASCII; :: NFD; :: [:Nonspacing Mark:] Remove; :: NFC;', \Transliterator::FORWARD);
|
||||||
|
|
||||||
|
return preg_replace('/[^A-Za-z0-9\- \']/', '', $transliterator->transliterate($title));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,15 +213,62 @@ class FeedControllerTest extends WallabagCoreTestCase
|
||||||
$config->setFeedToken('SUPERTOKEN');
|
$config->setFeedToken('SUPERTOKEN');
|
||||||
$config->setFeedLimit(null);
|
$config->setFeedLimit(null);
|
||||||
$em->persist($config);
|
$em->persist($config);
|
||||||
|
|
||||||
|
$entry1 = $em
|
||||||
|
->getRepository('WallabagCoreBundle:Entry')
|
||||||
|
->find(1)
|
||||||
|
;
|
||||||
|
|
||||||
|
$entry4 = $em
|
||||||
|
->getRepository('WallabagCoreBundle:Entry')
|
||||||
|
->find(4)
|
||||||
|
;
|
||||||
|
|
||||||
|
$now = new \DateTimeImmutable('now');
|
||||||
|
|
||||||
|
$day1 = $now->modify('-8 days');
|
||||||
|
$day2 = $now->modify('-6 days');
|
||||||
|
$day3 = $now->modify('-4 days');
|
||||||
|
$day4 = $now->modify('-2 days');
|
||||||
|
|
||||||
|
$entry1->setCreatedAt($day1);
|
||||||
|
$entry4->setCreatedAt($day2);
|
||||||
|
|
||||||
|
$property = (new \ReflectionObject($entry1))->getProperty('updatedAt');
|
||||||
|
$property->setAccessible(true);
|
||||||
|
$property->setValue($entry1, $day4);
|
||||||
|
|
||||||
|
$property = (new \ReflectionObject($entry4))->getProperty('updatedAt');
|
||||||
|
$property->setAccessible(true);
|
||||||
|
$property->setValue($entry4, $day3);
|
||||||
|
|
||||||
$em->flush();
|
$em->flush();
|
||||||
|
|
||||||
$client = $this->getClient();
|
$client = $this->getClient();
|
||||||
$client->request('GET', '/feed/admin/SUPERTOKEN/tags/foo');
|
|
||||||
|
|
||||||
|
// tag foo - without sort
|
||||||
|
$crawler = $client->request('GET', '/feed/admin/SUPERTOKEN/tags/foo');
|
||||||
$this->assertSame(200, $client->getResponse()->getStatusCode());
|
$this->assertSame(200, $client->getResponse()->getStatusCode());
|
||||||
|
$this->assertSame('test title entry4', $crawler->filterXPath('//feed/entry[1]/title')->text());
|
||||||
|
$this->assertSame('test title entry1', $crawler->filterXPath('//feed/entry[2]/title')->text());
|
||||||
|
|
||||||
$this->validateDom($client->getResponse()->getContent(), 'tag', 2, 'foo');
|
// tag foo - with sort created
|
||||||
|
$crawler = $client->request('GET', '/feed/admin/SUPERTOKEN/tags/foo?sort=created');
|
||||||
|
$this->assertSame(200, $client->getResponse()->getStatusCode());
|
||||||
|
$this->assertSame('test title entry4', $crawler->filterXPath('//feed/entry[1]/title')->text());
|
||||||
|
$this->assertSame('test title entry1', $crawler->filterXPath('//feed/entry[2]/title')->text());
|
||||||
|
|
||||||
|
// tag foo - with sort updated
|
||||||
|
$crawler = $client->request('GET', '/feed/admin/SUPERTOKEN/tags/foo?sort=updated');
|
||||||
|
$this->assertSame(200, $client->getResponse()->getStatusCode());
|
||||||
|
$this->assertSame('test title entry1', $crawler->filterXPath('//feed/entry[1]/title')->text());
|
||||||
|
$this->assertSame('test title entry4', $crawler->filterXPath('//feed/entry[2]/title')->text());
|
||||||
|
|
||||||
|
// tag foo - with invalid sort
|
||||||
|
$client->request('GET', '/feed/admin/SUPERTOKEN/tags/foo?sort=invalid');
|
||||||
|
$this->assertSame(400, $client->getResponse()->getStatusCode());
|
||||||
|
|
||||||
|
// tag foo/3000
|
||||||
$client->request('GET', '/feed/admin/SUPERTOKEN/tags/foo/3000');
|
$client->request('GET', '/feed/admin/SUPERTOKEN/tags/foo/3000');
|
||||||
$this->assertSame(302, $client->getResponse()->getStatusCode());
|
$this->assertSame(302, $client->getResponse()->getStatusCode());
|
||||||
}
|
}
|
||||||
|
|
|
@ -476,4 +476,35 @@ class TagControllerTest extends WallabagCoreTestCase
|
||||||
$this->assertNotFalse(array_search('cache', $tags, true), 'Tag cache is assigned to the entry');
|
$this->assertNotFalse(array_search('cache', $tags, true), 'Tag cache is assigned to the entry');
|
||||||
$this->assertNotFalse(array_search('caché', $tags, true), 'Tag caché is assigned to the entry');
|
$this->assertNotFalse(array_search('caché', $tags, true), 'Tag caché is assigned to the entry');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testAssignTagsOnSearchResults()
|
||||||
|
{
|
||||||
|
$this->logInAs('admin');
|
||||||
|
$client = $this->getClient();
|
||||||
|
|
||||||
|
// Search on unread list
|
||||||
|
$crawler = $client->request('GET', '/unread/list');
|
||||||
|
|
||||||
|
$form = $crawler->filter('form[name=search]')->form();
|
||||||
|
$data = [
|
||||||
|
'search_entry[term]' => 'title',
|
||||||
|
];
|
||||||
|
|
||||||
|
$crawler = $client->submit($form, $data);
|
||||||
|
|
||||||
|
$client->click($crawler->selectLink('entry.list.assign_search_tag')->link());
|
||||||
|
$client->followRedirect();
|
||||||
|
|
||||||
|
$entries = $client->getContainer()
|
||||||
|
->get('doctrine.orm.entity_manager')
|
||||||
|
->getRepository('WallabagCoreBundle:Entry')
|
||||||
|
->getBuilderForSearchByUser($this->getLoggedInUserId(), 'title', 'unread')
|
||||||
|
->getQuery()->getResult();
|
||||||
|
|
||||||
|
foreach ($entries as $entry) {
|
||||||
|
$tags = $entry->getTagsLabel();
|
||||||
|
|
||||||
|
$this->assertContains('title', $tags);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@ class DownloadImagesTest extends TestCase
|
||||||
['image/jpeg', 'jpeg'],
|
['image/jpeg', 'jpeg'],
|
||||||
['image/png', 'png'],
|
['image/png', 'png'],
|
||||||
['image/gif', 'gif'],
|
['image/gif', 'gif'],
|
||||||
|
['image/webp', 'webp'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -202,10 +202,29 @@ class RuleBasedTaggerTest extends TestCase
|
||||||
->method('satisfies')
|
->method('satisfies')
|
||||||
->willReturn(true);
|
->willReturn(true);
|
||||||
|
|
||||||
$this->rulerz
|
$query = $this->getMockBuilder('Doctrine\ORM\AbstractQuery')
|
||||||
->method('filter')
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
|
||||||
|
$query
|
||||||
|
->expects($this->once())
|
||||||
|
->method('getResult')
|
||||||
->willReturn([new Entry($user), new Entry($user)]);
|
->willReturn([new Entry($user), new Entry($user)]);
|
||||||
|
|
||||||
|
$qb = $this->getMockBuilder('Doctrine\ORM\QueryBuilder')
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
|
||||||
|
$qb
|
||||||
|
->expects($this->once())
|
||||||
|
->method('getQuery')
|
||||||
|
->willReturn($query);
|
||||||
|
|
||||||
|
$this->entryRepository
|
||||||
|
->expects($this->once())
|
||||||
|
->method('getBuilderForAllByUser')
|
||||||
|
->willReturn($qb);
|
||||||
|
|
||||||
$entries = $this->tagger->tagAllForUser($user);
|
$entries = $this->tagger->tagAllForUser($user);
|
||||||
|
|
||||||
$this->assertCount(2, $entries);
|
$this->assertCount(2, $entries);
|
||||||
|
@ -222,6 +241,7 @@ class RuleBasedTaggerTest extends TestCase
|
||||||
{
|
{
|
||||||
$user = new User();
|
$user = new User();
|
||||||
$config = new Config($user);
|
$config = new Config($user);
|
||||||
|
$config->setReadingSpeed(200);
|
||||||
|
|
||||||
$user->setConfig($config);
|
$user->setConfig($config);
|
||||||
|
|
||||||
|
|
|
@ -114,13 +114,13 @@ class ChromeControllerTest extends WallabagCoreTestCase
|
||||||
->get('doctrine.orm.entity_manager')
|
->get('doctrine.orm.entity_manager')
|
||||||
->getRepository('WallabagCoreBundle:Entry')
|
->getRepository('WallabagCoreBundle:Entry')
|
||||||
->findByUrlAndUserId(
|
->findByUrlAndUserId(
|
||||||
'https://www.usinenouvelle.com/article/la-multiplication-des-chefs-de-projet-est-une-catastrophe-manageriale-majeure-affirme-le-sociologue-francois-dupuy.N307730',
|
'https://www.20minutes.fr/sport/3256363-20220321-tournoi-vi-nations-trophee-gagne-xv-france-fini-fond-seine',
|
||||||
$this->getLoggedInUserId()
|
$this->getLoggedInUserId()
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $content);
|
$this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $content);
|
||||||
$this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.usinenouvelle.com is ok');
|
$this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for https://www.20minutes.fr is ok');
|
||||||
$this->assertNotEmpty($content->getLanguage(), 'Language for http://www.usinenouvelle.com is ok');
|
$this->assertNotEmpty($content->getLanguage(), 'Language for https://www.20minutes.fr is ok');
|
||||||
$this->assertCount(1, $content->getTags());
|
$this->assertCount(1, $content->getTags());
|
||||||
|
|
||||||
$createdAt = $content->getCreatedAt();
|
$createdAt = $content->getCreatedAt();
|
||||||
|
|
|
@ -1,38 +1,36 @@
|
||||||
{
|
{
|
||||||
"checksum": "f3aa0e9c0edad632a246f7e98ec64918",
|
"checksum": "f3aa0e9c0edad632a246f7e98ec64918",
|
||||||
"roots": {
|
"roots": {
|
||||||
"bookmark_bar": {
|
"bookmark_bar": {
|
||||||
"children": [
|
"children": [ {
|
||||||
{
|
"date_added": "13118850929335823",
|
||||||
"date_added": "13118850929335823",
|
"id": "6",
|
||||||
"id": "6",
|
"name": "Tournoi des VI Nations : Le trophée gagné par le XV de France a-t-il fini au fond de la Seine ?",
|
||||||
"name": "\"La multiplication des chefs de projet est une catastrophe managériale majeure\", affirme le sociologue François Dupuy - Ressources humaines",
|
"type": "url",
|
||||||
"type": "url",
|
"url": "https://www.20minutes.fr/sport/3256363-20220321-tournoi-vi-nations-trophee-gagne-xv-france-fini-fond-seine"
|
||||||
"url": "http://www.usinenouvelle.com/article/la-multiplication-des-chefs-de-projet-est-une-catastrophe-manageriale-majeure-affirme-le-sociologue-francois-dupuy.N307730"
|
} ],
|
||||||
}
|
"date_added": "13118829474385693",
|
||||||
],
|
"date_modified": "13118850929335823",
|
||||||
"date_added": "13118829474385693",
|
"id": "1",
|
||||||
"date_modified": "13118850929335823",
|
"name": "Barre de favoris",
|
||||||
"id": "1",
|
"type": "folder"
|
||||||
"name": "Barre de favoris",
|
},
|
||||||
"type": "folder"
|
"other": {
|
||||||
},
|
"children": [ ],
|
||||||
"other": {
|
"date_added": "13118829474385701",
|
||||||
"children": [],
|
"date_modified": "0",
|
||||||
"date_added": "13118829474385701",
|
"id": "2",
|
||||||
"date_modified": "0",
|
"name": "Autres favoris",
|
||||||
"id": "2",
|
"type": "folder"
|
||||||
"name": "Autres favoris",
|
},
|
||||||
"type": "folder"
|
"synced": {
|
||||||
},
|
"children": [ ],
|
||||||
"synced": {
|
"date_added": "13118829474385702",
|
||||||
"children": [],
|
"date_modified": "0",
|
||||||
"date_added": "13118829474385702",
|
"id": "3",
|
||||||
"date_modified": "0",
|
"name": "Favoris sur mobile",
|
||||||
"id": "3",
|
"type": "folder"
|
||||||
"name": "Favoris sur mobile",
|
}
|
||||||
"type": "folder"
|
},
|
||||||
}
|
"version": 1
|
||||||
},
|
|
||||||
"version": 1
|
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue