1
0
Fork 0
mirror of https://github.com/wallabag/wallabag.git synced 2025-09-30 19:22:12 +00:00
This commit is contained in:
Harm te Molder 2025-08-21 10:21:22 +02:00
commit c91a0fa8f5
No known key found for this signature in database
GPG key ID: 74A98B5EEF1920BA
465 changed files with 11366 additions and 10396 deletions

View file

@ -1,10 +0,0 @@
{
"presets": [
[
"@babel/preset-env",
{
"modules": false
}
]
]
}

View file

@ -1,6 +1,9 @@
{ {
"extends": "airbnb-base", "extends": "airbnb-base",
"parser": "@babel/eslint-parser", "parser": "@babel/eslint-parser",
"parserOptions": {
"requireConfigFile": false
},
"env": { "env": {
"browser": true, "browser": true,
"es6": true "es6": true

2
.github/CODEOWNERS vendored Normal file
View file

@ -0,0 +1,2 @@
# Migrated rules from dependabot.yml
composer.* @Kdecherf @j0k3r @yguedidi

View file

@ -24,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.4. - Ensure you are running PHP >= 8.2.
- 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)
@ -55,3 +55,7 @@ To run the tests locally run `make test`.
To run the PHP formatter run `make fix-cs`. To run the PHP formatter run `make fix-cs`.
To run the PHPStan static analysis run `make phpstan`. To run the PHPStan static analysis run `make phpstan`.
To run the JS linter run `make lint-js`.
To run the SCSS linter run `make lint-scss`.

View file

@ -15,13 +15,13 @@ updates:
patterns: patterns:
- "*fontsource*" - "*fontsource*"
ignore: ignore:
- dependency-name: materialize-css - dependency-name: "@materializecss/materialize"
versions: versions:
- "> 0.98.2" - "> 1.2.2"
- package-ecosystem: composer - package-ecosystem: composer
directory: "/" directory: "/"
schedule: schedule:
interval: daily interval: weekly
time: "04:00" time: "04:00"
timezone: Europe/Paris timezone: Europe/Paris
open-pull-requests-limit: 10 open-pull-requests-limit: 10
@ -35,18 +35,9 @@ updates:
phpstan-dependencies: phpstan-dependencies:
patterns: patterns:
- "phpstan/*" - "phpstan/*"
reviewers:
- j0k3r
- yguedidi
- Kdecherf
ignore: ignore:
- dependency-name: lcobucci/jwt
versions:
- ">= 4.2.0"
# until we add support for Symfony 5+
- dependency-name: symfony/* - dependency-name: symfony/*
versions: update-types: [ "version-update:semver-major" ]
- ">= 5.0.0"
- package-ecosystem: github-actions - package-ecosystem: github-actions
directory: "/" directory: "/"
schedule: schedule:

View file

@ -13,23 +13,29 @@ permissions:
jobs: jobs:
coding-standards: coding-standards:
name: "CS Fixer, PHPStan & TwigCS" name: "CS Fixer, PHPStan & TwigCS"
runs-on: "ubuntu-20.04" runs-on: ubuntu-latest
steps: steps:
- name: "Checkout" - name: "Checkout"
uses: "actions/checkout@v4" uses: "actions/checkout@v5"
- 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: "8.2"
tools: cs2pr, pecl tools: cs2pr, pecl
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:
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Install Node"
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"
cache: 'yarn'
- name: "Setup MySQL" - name: "Setup MySQL"
run: | run: |
sudo systemctl start mysql.service sudo systemctl start mysql.service
@ -37,24 +43,48 @@ jobs:
cp app/config/tests/parameters_test.mysql.yml app/config/parameters_test.yml cp app/config/tests/parameters_test.mysql.yml app/config/parameters_test.yml
- name: "Install dependencies with Composer" - name: "Install dependencies with Composer"
id: composer-install
uses: "ramsey/composer-install@v3" uses: "ramsey/composer-install@v3"
with: with:
composer-options: "--optimize-autoloader --prefer-dist" composer-options: "--optimize-autoloader --prefer-dist"
- name: "Install dependencies with Yarn"
id: yarn-install
run: yarn install
- name: "Run Composer validate"
if: always() && steps.composer-install.outcome == 'success'
run: "composer validate"
- name: "Run Composer dependency analyser" - name: "Run Composer dependency analyser"
if: always() && steps.composer-install.outcome == 'success'
run: "bin/composer-dependency-analyser" run: "bin/composer-dependency-analyser"
- name: "Run PHP CS Fixer" - name: "Run PHP CS Fixer"
if: always() && steps.composer-install.outcome == 'success'
run: "bin/php-cs-fixer fix --verbose --dry-run --format=checkstyle | cs2pr" run: "bin/php-cs-fixer fix --verbose --dry-run --format=checkstyle | cs2pr"
- name: "Generate test cache for PHPStan" - name: "Generate test cache for PHPStan"
id: test-cache
if: always() && steps.composer-install.outcome == 'success'
run: "php bin/console cache:clear --env=test" run: "php bin/console cache:clear --env=test"
- name: "Run PHPStan" - name: "Run PHPStan"
if: always() && steps.test-cache.outcome == 'success'
run: "php bin/phpstan analyse --no-progress --error-format=checkstyle | cs2pr" run: "php bin/phpstan analyse --no-progress --error-format=checkstyle | cs2pr"
- name: "Run TwigCS" - name: "Run TwigCS"
if: always() && steps.composer-install.outcome == 'success'
run: "php bin/twigcs --severity=error --display=blocking --reporter checkstyle app/ src/ | cs2pr" run: "php bin/twigcs --severity=error --display=blocking --reporter checkstyle app/ src/ | cs2pr"
- name: "Run ergebnis/composer-normalize" - name: "Run ergebnis/composer-normalize"
if: always() && steps.composer-install.outcome == 'success'
run: "composer normalize --dry-run --no-check-lock" run: "composer normalize --dry-run --no-check-lock"
- name: "Run ESLint"
if: always() && steps.yarn-install.outcome == 'success'
run: "yarn lint:js"
- name: "Run Stylelint"
if: always() && steps.yarn-install.outcome == 'success'
run: "yarn lint:scss"

View file

@ -16,7 +16,7 @@ env:
jobs: jobs:
phpunit: phpunit:
name: "PHP ${{ matrix.php }} using ${{ matrix.database }}" name: "PHP ${{ matrix.php }} using ${{ matrix.database }}"
runs-on: "ubuntu-20.04" runs-on: ubuntu-latest
services: services:
rabbitmq: rabbitmq:
image: rabbitmq:3-alpine image: rabbitmq:3-alpine
@ -31,9 +31,6 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
php: php:
- "7.4"
- "8.0"
- "8.1"
- "8.2" - "8.2"
- "8.3" - "8.3"
- "8.4" - "8.4"
@ -44,7 +41,7 @@ jobs:
steps: steps:
- name: "Checkout" - name: "Checkout"
uses: "actions/checkout@v4" uses: "actions/checkout@v5"
with: with:
fetch-depth: 2 fetch-depth: 2
@ -57,6 +54,12 @@ jobs:
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"
- name: "Install Node"
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"
cache: 'yarn'
- name: "Setup MySQL" - name: "Setup MySQL"
if: "${{ matrix.database == 'mysql' }}" if: "${{ matrix.database == 'mysql' }}"
run: | run: |
@ -76,6 +79,12 @@ jobs:
with: with:
composer-options: "--optimize-autoloader --prefer-dist" composer-options: "--optimize-autoloader --prefer-dist"
- name: "Install dependencies with Yarn"
run: yarn install
- name: "Build assets with Yarn"
run: yarn build:dev
- name: "Prepare database configuration" - name: "Prepare database configuration"
run: cp app/config/tests/parameters_test.${{ matrix.database }}.yml app/config/parameters_test.yml run: cp app/config/tests/parameters_test.${{ matrix.database }}.yml app/config/parameters_test.yml
@ -84,7 +93,7 @@ jobs:
phpunit_no_prefix: phpunit_no_prefix:
name: "PHP ${{ matrix.php }} using ${{ matrix.database }} without prefix" name: "PHP ${{ matrix.php }} using ${{ matrix.database }} without prefix"
runs-on: "ubuntu-20.04" runs-on: ubuntu-latest
services: services:
rabbitmq: rabbitmq:
image: rabbitmq:3-alpine image: rabbitmq:3-alpine
@ -107,7 +116,7 @@ jobs:
steps: steps:
- name: "Checkout" - name: "Checkout"
uses: "actions/checkout@v4" uses: "actions/checkout@v5"
with: with:
fetch-depth: 2 fetch-depth: 2
@ -120,6 +129,12 @@ jobs:
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"
- name: "Install Node"
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"
cache: 'yarn'
- name: "Remove database prefix" - name: "Remove database prefix"
run: | run: |
pip install --user yq pip install --user yq
@ -144,6 +159,12 @@ jobs:
with: with:
composer-options: "--optimize-autoloader --prefer-dist" composer-options: "--optimize-autoloader --prefer-dist"
- name: "Install dependencies with Yarn"
run: yarn install
- name: "Build assets with Yarn"
run: yarn build:dev
- name: "Prepare database configuration" - name: "Prepare database configuration"
run: cp app/config/tests/parameters_test.${{ matrix.database }}.yml app/config/parameters_test.yml run: cp app/config/tests/parameters_test.${{ matrix.database }}.yml app/config/parameters_test.yml
@ -152,7 +173,7 @@ jobs:
phpunit-without-rmq-redis: phpunit-without-rmq-redis:
name: "PHP ${{ matrix.php }} using ${{ matrix.database }} without Rabbit & Redis" name: "PHP ${{ matrix.php }} using ${{ matrix.database }} without Rabbit & Redis"
runs-on: "ubuntu-20.04" runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false fail-fast: false
@ -166,7 +187,7 @@ jobs:
steps: steps:
- name: "Checkout" - name: "Checkout"
uses: "actions/checkout@v4" uses: "actions/checkout@v5"
with: with:
fetch-depth: 2 fetch-depth: 2
@ -179,6 +200,12 @@ jobs:
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"
- name: "Install Node"
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"
cache: 'yarn'
- name: "Setup MySQL" - name: "Setup MySQL"
if: "${{ matrix.database == 'mysql' }}" if: "${{ matrix.database == 'mysql' }}"
run: | run: |
@ -198,6 +225,12 @@ jobs:
with: with:
composer-options: "--optimize-autoloader --prefer-dist" composer-options: "--optimize-autoloader --prefer-dist"
- name: "Install dependencies with Yarn"
run: yarn install
- name: "Build assets with Yarn"
run: yarn build:dev
- name: "Prepare database configuration" - name: "Prepare database configuration"
run: cp app/config/tests/parameters_test.${{ matrix.database }}.yml app/config/parameters_test.yml run: cp app/config/tests/parameters_test.${{ matrix.database }}.yml app/config/parameters_test.yml

View file

@ -12,7 +12,7 @@ jobs:
steps: steps:
- name: Dependabot metadata - name: Dependabot metadata
id: metadata id: metadata
uses: dependabot/fetch-metadata@v2.2.0 uses: dependabot/fetch-metadata@v2.4.0
with: with:
github-token: '${{ secrets.GITHUB_TOKEN }}' github-token: '${{ secrets.GITHUB_TOKEN }}'
- name: Approve and merge minor updates - name: Approve and merge minor updates

View file

@ -13,16 +13,16 @@ permissions:
jobs: jobs:
translations: translations:
name: "Translations" name: "Translations"
runs-on: "ubuntu-20.04" runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
php: php:
- "7.4" - "8.2"
steps: steps:
- name: "Checkout" - name: "Checkout"
uses: "actions/checkout@v4" uses: "actions/checkout@v5"
- name: "Install PHP" - name: "Install PHP"
uses: "shivammathur/setup-php@v2" uses: "shivammathur/setup-php@v2"

View file

@ -12,11 +12,11 @@ jobs:
strategy: strategy:
matrix: matrix:
php: php:
- "7.4" - "8.2"
steps: steps:
- name: "Checkout" - name: "Checkout"
uses: "actions/checkout@v4" uses: "actions/checkout@v5"
- name: "Install PHP" - name: "Install PHP"
uses: "shivammathur/setup-php@v2" uses: "shivammathur/setup-php@v2"

4
.gitignore vendored
View file

@ -29,7 +29,7 @@ web/uploads/
!/web/bundles/.gitkeep !/web/bundles/.gitkeep
/web/assets/images/* /web/assets/images/*
!web/assets/images/.gitkeep !web/assets/images/.gitkeep
/web/wallassets/* /web/build/*
# Build # Build
/app/build /app/build
@ -60,3 +60,5 @@ specialexport.json
web/custom.css web/custom.css
.env.local .env.local
yarn-error.log

View file

@ -37,17 +37,6 @@ return $config
// 'psr_autoloading' => true, // 'psr_autoloading' => true,
'strict_comparison' => true, 'strict_comparison' => true,
'strict_param' => true, 'strict_param' => true,
// We override next rule because of current @Symfony ruleSet
// 'parameters' element is breaking PHP 7.4
// https://cs.symfony.com/doc/rules/control_structure/trailing_comma_in_multiline.html
// TODO: remove this configuration after dropping support of PHP 7.4
'trailing_comma_in_multiline' => [
'elements' => [
'arrays',
'array_destructuring',
'match',
],
],
'concat_space' => [ 'concat_space' => [
'spacing' => 'one', 'spacing' => 'one',
], ],

View file

@ -1,5 +1,51 @@
# Changelog # Changelog
## Upcoming changes
* **[BC BREAK]** Convert 403 errors to 404 errors by @yguedidi in https://github.com/wallabag/wallabag/pull/8075
* `wallassets/` folder renamed to `build/`
## [2.6.13](https://github.com/wallabag/wallabag/tree/2.6.13)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.12...2.6.13)
### Improvements
* Add support of Pocket CSV import by @kdecherf and @nicosomb in [https://github.com/wallabag/wallabag/pull/8240](https://github.com/wallabag/wallabag/pull/8240)
* Backport Pocket and Shaarli HTML imports from master by @nicosomb in [https://github.com/wallabag/wallabag/pull/8193](https://github.com/wallabag/wallabag/pull/8193)
### Fixes
* Avoid non-validated OTP to be enabled #8139 by @j0k3r in [https://github.com/wallabag/wallabag/pull/8139](https://github.com/wallabag/wallabag/pull/8139)
### Technical stuff
* Update j0k3r/php-readability:1.2.13 to fix regression (about latin1 instead of UTF-8 used for entries) by @nicosomb [https://github.com/wallabag/wallabag/pull/8194](https://github.com/wallabag/wallabag/pull/8194)
## [2.6.12](https://github.com/wallabag/wallabag/tree/2.6.12)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.11...2.6.12)
### Technical stuff
* Fix changelog by @yguedidi in [https://github.com/wallabag/wallabag/pull/8135](https://github.com/wallabag/wallabag/pull/8135)
* Update dependencies by @yguedidi in [https://github.com/wallabag/wallabag/pull/8136](https://github.com/wallabag/wallabag/pull/8136)
## [2.6.11](https://github.com/wallabag/wallabag/tree/2.6.11)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.10...2.6.11)
### Security fix
* Protect actions with a CSRF token by @yguedidi in https://github.com/wallabag/wallabag/commit/99c8a06594d6ee7480ce4d041ccff3025b353656
### Fixes
* Fix redirection after action in search results by @nicosomb in [https://github.com/wallabag/wallabag/pull/7827](https://github.com/wallabag/wallabag/pull/7827)
* Fix title tag filter by @nicosomb in [https://github.com/wallabag/wallabag/pull/7846](https://github.com/wallabag/wallabag/pull/7846)
* Change NB_ELEMENTS in pocket importer to 30 by @j0k3r in [https://github.com/wallabag/wallabag/pull/7993](https://github.com/wallabag/wallabag/pull/7993)
* Fix entries counter for annotated entries in the menu by @j0k3r in [https://github.com/wallabag/wallabag/pull/7999](https://github.com/wallabag/wallabag/pull/7999)
### Technical stuff
* Prepare 2.6.11 release by @yguedidi in [https://github.com/wallabag/wallabag/pull/8133](https://github.com/wallabag/wallabag/pull/8133)
## [2.6.10](https://github.com/wallabag/wallabag/tree/2.6.10) ## [2.6.10](https://github.com/wallabag/wallabag/tree/2.6.10)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.9...2.6.10) [Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.9...2.6.10)

View file

@ -52,6 +52,15 @@ fix-cs: ## Run PHP-CS-Fixer
phpstan: ## Run PHPStan phpstan: ## Run PHPStan
@$(PHP_NO_XDEBUG) bin/phpstan analyse @$(PHP_NO_XDEBUG) bin/phpstan analyse
phpstan-baseline: ## Generate PHPStan baseline
@$(PHP_NO_XDEBUG) bin/phpstan analyse --generate-baseline
lint-js: ## Run ESLint
@$(YARN) lint:js
lint-scss: ## Run Stylelint
@$(YARN) lint:scss
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
$(error VERSION is not set) $(error VERSION is not set)

View file

@ -1,6 +1,6 @@
# wallabag # wallabag
![CI](https://github.com/wallabag/wallabag/workflows/CI/badge.svg) [![CI](https://github.com/wallabag/wallabag/actions/workflows/continuous-integration.yml/badge.svg?branch=master)](https://github.com/wallabag/wallabag/actions/workflows/continuous-integration.yml?query=branch%3Amaster)
[![Matrix](https://matrix.to/img/matrix-badge.svg)](https://matrix.to/#/#wallabag:matrix.org) [![Matrix](https://matrix.to/img/matrix-badge.svg)](https://matrix.to/#/#wallabag:matrix.org)
[![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)

View file

@ -25,13 +25,13 @@ During this documentation, we assume the release is `$LAST_WALLABAG_RELEASE` (li
### Target PHP version ### Target PHP version
`composer.lock` is _always_ built for a particular version, by default the one it is generated (with `composer update`). `composer.lock` is _always_ built for a particular version, by default the one it is generated (with `composer update`).
If the PHP version used to generate the .lock isn't a widely available one (like PHP 8), a more common one should If the PHP version used to generate the .lock isn't a widely available one (like latest PHP versions), a more common one should
be locally specified in `composer.lock`: be locally specified in `composer.lock`:
```json ```json
"config": { "config": {
"platform": { "platform": {
"php": "7.4.29", "php": "8.2.27",
"ext-something": "4.0" "ext-something": "4.0"
} }
} }

View file

@ -1,8 +1,39 @@
<?php <?php
use BabDev\PagerfantaBundle\BabDevPagerfantaBundle;
use Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle;
use Craue\ConfigBundle\CraueConfigBundle;
use DAMA\DoctrineTestBundle\DAMADoctrineTestBundle;
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
use Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle;
use Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle;
use FOS\JsRoutingBundle\FOSJsRoutingBundle;
use FOS\OAuthServerBundle\FOSOAuthServerBundle;
use FOS\RestBundle\FOSRestBundle;
use FOS\UserBundle\FOSUserBundle;
use JMS\SerializerBundle\JMSSerializerBundle;
use KPhoen\RulerZBundle\KPhoenRulerZBundle;
use Nelmio\ApiDocBundle\NelmioApiDocBundle;
use Nelmio\CorsBundle\NelmioCorsBundle;
use OldSound\RabbitMqBundle\OldSoundRabbitMqBundle;
use Scheb\TwoFactorBundle\SchebTwoFactorBundle;
use Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle;
use Sentry\SentryBundle\SentryBundle;
use Spiriit\Bundle\FormFilterBundle\SpiriitFormFilterBundle;
use Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle;
use Symfony\Bundle\DebugBundle\DebugBundle;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Bundle\MakerBundle\MakerBundle;
use Symfony\Bundle\MonologBundle\MonologBundle;
use Symfony\Bundle\SecurityBundle\SecurityBundle;
use Symfony\Bundle\TwigBundle\TwigBundle;
use Symfony\Bundle\WebProfilerBundle\WebProfilerBundle;
use Symfony\Bundle\WebServerBundle\WebServerBundle;
use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\Kernel;
use Symfony\WebpackEncoreBundle\WebpackEncoreBundle;
use Twig\Extra\TwigExtraBundle\TwigExtraBundle;
use Wallabag\Import\ImportCompilerPass; use Wallabag\Import\ImportCompilerPass;
class AppKernel extends Kernel class AppKernel extends Kernel
@ -10,45 +41,45 @@ class AppKernel extends Kernel
public function registerBundles() public function registerBundles()
{ {
$bundles = [ $bundles = [
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), new FrameworkBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(), new SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(), new TwigBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(), new MonologBundle(),
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(), new DoctrineBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(), new SensioFrameworkExtraBundle(),
new FOS\RestBundle\FOSRestBundle(), new FOSRestBundle(),
new FOS\UserBundle\FOSUserBundle(), new FOSUserBundle(),
new JMS\SerializerBundle\JMSSerializerBundle(), new JMSSerializerBundle(),
new Nelmio\ApiDocBundle\NelmioApiDocBundle(), new NelmioApiDocBundle(),
new Nelmio\CorsBundle\NelmioCorsBundle(), new NelmioCorsBundle(),
new Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle(), new BazingaHateoasBundle(),
new Spiriit\Bundle\FormFilterBundle\SpiriitFormFilterBundle(), new SpiriitFormFilterBundle(),
new FOS\OAuthServerBundle\FOSOAuthServerBundle(), new FOSOAuthServerBundle(),
new Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle(), new StofDoctrineExtensionsBundle(),
new Scheb\TwoFactorBundle\SchebTwoFactorBundle(), new SchebTwoFactorBundle(),
new KPhoen\RulerZBundle\KPhoenRulerZBundle(), new KPhoenRulerZBundle(),
new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(), new DoctrineMigrationsBundle(),
new Craue\ConfigBundle\CraueConfigBundle(), new CraueConfigBundle(),
new BabDev\PagerfantaBundle\BabDevPagerfantaBundle(), new BabDevPagerfantaBundle(),
new FOS\JsRoutingBundle\FOSJsRoutingBundle(), new FOSJsRoutingBundle(),
new OldSound\RabbitMqBundle\OldSoundRabbitMqBundle(), new OldSoundRabbitMqBundle(),
new Http\HttplugBundle\HttplugBundle(), new SentryBundle(),
new Sentry\SentryBundle\SentryBundle(), new TwigExtraBundle(),
new Twig\Extra\TwigExtraBundle\TwigExtraBundle(), new WebpackEncoreBundle(),
]; ];
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) { if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
$bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle(); $bundles[] = new DebugBundle();
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); $bundles[] = new WebProfilerBundle();
$bundles[] = new Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle(); $bundles[] = new DoctrineFixturesBundle();
if ('test' === $this->getEnvironment()) { if ('test' === $this->getEnvironment()) {
$bundles[] = new DAMA\DoctrineTestBundle\DAMADoctrineTestBundle(); $bundles[] = new DAMADoctrineTestBundle();
} }
if ('dev' === $this->getEnvironment()) { if ('dev' === $this->getEnvironment()) {
$bundles[] = new Symfony\Bundle\MakerBundle\MakerBundle(); $bundles[] = new MakerBundle();
$bundles[] = new Symfony\Bundle\WebServerBundle\WebServerBundle(); $bundles[] = new WebServerBundle();
} }
} }
@ -69,30 +100,16 @@ class AppKernel extends Kernel
{ {
$loader->load($this->getProjectDir() . '/app/config/config_' . $this->getEnvironment() . '.yml'); $loader->load($this->getProjectDir() . '/app/config/config_' . $this->getEnvironment() . '.yml');
$loader->load(function ($container) { $loader->load(function (ContainerBuilder $container): void {
if ($container->getParameter('use_webpack_dev_server')) {
$container->loadFromExtension('framework', [
'assets' => [
'base_url' => 'http://localhost:8080/',
],
]);
} else {
$container->loadFromExtension('framework', [
'assets' => [
'base_url' => $container->getParameter('domain_name'),
],
]);
}
});
$loader->load(function (ContainerBuilder $container) {
// $container->setParameter('container.autowiring.strict_mode', true); // $container->setParameter('container.autowiring.strict_mode', true);
// $container->setParameter('container.dumper.inline_class_loader', true); // $container->setParameter('container.dumper.inline_class_loader', true);
$container->addObjectResource($this); $container->addObjectResource($this);
}); });
$loader->load(function (ContainerBuilder $container) { $loader->load(function (ContainerBuilder $container): void {
$this->processDatabaseParameters($container); $this->processDatabaseParameters($container);
$this->defineRedisUrlEnvVar($container);
$this->defineRabbitMqUrlEnvVar($container);
}); });
} }
@ -103,19 +120,12 @@ class AppKernel extends Kernel
private function processDatabaseParameters(ContainerBuilder $container) private function processDatabaseParameters(ContainerBuilder $container)
{ {
switch ($container->getParameter('database_driver')) { $scheme = match ($container->getParameter('database_driver')) {
case 'pdo_mysql': 'pdo_mysql' => 'mysql',
$scheme = 'mysql'; 'pdo_pgsql' => 'pgsql',
break; 'pdo_sqlite' => 'sqlite',
case 'pdo_pgsql': default => throw new RuntimeException('Unsupported database driver: ' . $container->getParameter('database_driver')),
$scheme = 'pgsql'; };
break;
case 'pdo_sqlite':
$scheme = 'sqlite';
break;
default:
throw new RuntimeException('Unsupported database driver: ' . $container->getParameter('database_driver'));
}
$container->setParameter('database_scheme', $scheme); $container->setParameter('database_scheme', $scheme);
@ -128,4 +138,45 @@ class AppKernel extends Kernel
$container->setParameter('database_port', (string) $container->getParameter('database_port')); $container->setParameter('database_port', (string) $container->getParameter('database_port'));
$container->setParameter('database_socket', (string) $container->getParameter('database_socket')); $container->setParameter('database_socket', (string) $container->getParameter('database_socket'));
} }
private function defineRedisUrlEnvVar(ContainerBuilder $container)
{
$scheme = $container->getParameter('redis_scheme');
$host = $container->getParameter('redis_host');
$port = $container->getParameter('redis_port');
$path = $container->getParameter('redis_path');
$password = $container->getParameter('redis_password');
$url = $scheme . '://';
if ($password) {
$url .= $password . '@';
}
$url .= $host;
if ($port) {
$url .= ':' . $port;
}
$url .= '/' . ltrim($path, '/');
$container->setParameter('env(REDIS_URL)', $url);
}
private function defineRabbitMqUrlEnvVar(ContainerBuilder $container)
{
$host = $container->getParameter('rabbitmq_host');
$port = $container->getParameter('rabbitmq_port');
$user = $container->getParameter('rabbitmq_user');
$password = $container->getParameter('rabbitmq_password');
$url = 'amqp://' . $user . ':' . $password . '@' . $host;
if ($port) {
$url .= ':' . $port;
}
$container->setParameter('env(RABBITMQ_URL)', $url);
}
} }

View file

@ -5,8 +5,6 @@ imports:
- { resource: wallabag.yml } - { resource: wallabag.yml }
parameters: parameters:
# Allows to use the live reload feature for changes in assets
use_webpack_dev_server: false
craue_config.cache_adapter.class: Craue\ConfigBundle\CacheAdapter\SymfonyCacheComponentAdapter craue_config.cache_adapter.class: Craue\ConfigBundle\CacheAdapter\SymfonyCacheComponentAdapter
env(DATABASE_URL): '%database_scheme%://%database_user%:%database_password%@%database_host%:%database_port%/%database_name%?unix_socket=%database_socket%&charset=%database_charset%' env(DATABASE_URL): '%database_scheme%://%database_user%:%database_password%@%database_host%:%database_port%/%database_name%?unix_socket=%database_socket%&charset=%database_charset%'
@ -31,9 +29,13 @@ framework:
handler_id: session.handler.native_file handler_id: session.handler.native_file
save_path: "%kernel.project_dir%/var/sessions/%kernel.environment%" save_path: "%kernel.project_dir%/var/sessions/%kernel.environment%"
cookie_secure: auto cookie_secure: auto
cookie_samesite: lax
storage_factory_id: session.storage.factory.native
fragments: ~ fragments: ~
http_method_override: true http_method_override: true
assets: ~ assets:
base_url: '%domain_name%'
json_manifest_path: '%kernel.project_dir%/web/build/manifest.json'
mailer: mailer:
dsn: "%mailer_dsn%" dsn: "%mailer_dsn%"
http_client: http_client:
@ -47,6 +49,10 @@ framework:
X-Accept: 'application/json' X-Accept: 'application/json'
request_html_function.client: request_html_function.client:
scope: '.*' scope: '.*'
browser.client:
scope: '.*'
verify_host: false
verify_peer: false
# Twig Configuration # Twig Configuration
twig: twig:
@ -56,6 +62,7 @@ twig:
form_themes: form_themes:
- "@SpiriitFormFilter/Form/form_div_layout.html.twig" - "@SpiriitFormFilter/Form/form_div_layout.html.twig"
globals: globals:
wallabag_url: '%domain_name%'
registration_enabled: '%fosuser_registration%' registration_enabled: '%fosuser_registration%'
# Doctrine Configuration # Doctrine Configuration
@ -72,7 +79,7 @@ doctrine:
auto_mapping: true auto_mapping: true
mappings: mappings:
Wallabag: Wallabag:
type: annotation type: attribute
is_bundle: false is_bundle: false
dir: '%kernel.project_dir%/src/Entity' dir: '%kernel.project_dir%/src/Entity'
prefix: 'Wallabag\Entity' prefix: 'Wallabag\Entity'
@ -95,6 +102,8 @@ doctrine_migrations:
version_column_name: 'version' version_column_name: 'version'
version_column_length: 192 version_column_length: 192
executed_at_column_name: 'executed_at' executed_at_column_name: 'executed_at'
services:
Doctrine\Migrations\Version\MigrationFactory: Wallabag\Doctrine\MigrationFactoryDecorator
fos_rest: fos_rest:
param_fetcher_listener: true param_fetcher_listener: true
@ -190,7 +199,7 @@ fos_user:
address: "%from_email%" address: "%from_email%"
sender_name: wallabag sender_name: wallabag
service: service:
mailer: Wallabag\Mailer\UserMailer mailer: fos_user.mailer.twig_symfony
fos_oauth_server: fos_oauth_server:
db_driver: orm db_driver: orm
@ -225,18 +234,10 @@ scheb_two_factor:
template: "Authentication/form.html.twig" template: "Authentication/form.html.twig"
mailer: Wallabag\Mailer\AuthCodeMailer mailer: Wallabag\Mailer\AuthCodeMailer
rulerz:
targets:
doctrine: true
old_sound_rabbit_mq: old_sound_rabbit_mq:
connections: connections:
default: default:
host: "%rabbitmq_host%" url: "%env(RABBITMQ_URL)%"
port: "%rabbitmq_port%"
user: "%rabbitmq_user%"
password: "%rabbitmq_password%"
vhost: /
lazy: true lazy: true
producers: producers:
import_pocket: import_pocket:
@ -304,6 +305,11 @@ old_sound_rabbit_mq:
exchange_options: exchange_options:
name: 'wallabag.import.pocket_html' name: 'wallabag.import.pocket_html'
type: topic type: topic
import_pocket_csv:
connection: default
exchange_options:
name: 'wallabag.import.pocket_csv'
type: topic
consumers: consumers:
import_pocket: import_pocket:
connection: default connection: default
@ -422,6 +428,15 @@ old_sound_rabbit_mq:
name: 'wallabag.import.pocket_html' name: 'wallabag.import.pocket_html'
callback: wallabag.consumer.amqp.pocket_html callback: wallabag.consumer.amqp.pocket_html
qos_options: {prefetch_count: "%rabbitmq_prefetch_count%"} qos_options: {prefetch_count: "%rabbitmq_prefetch_count%"}
import_pocket_csv:
connection: default
exchange_options:
name: 'wallabag.import.pocket_csv'
type: topic
queue_options:
name: 'wallabag.import.pocket_csv'
callback: wallabag.consumer.amqp.pocket_csv
qos_options: {prefetch_count: "%rabbitmq_prefetch_count%"}
fos_js_routing: fos_js_routing:
routes_to_expose: routes_to_expose:
@ -449,17 +464,6 @@ sensio_framework_extra:
router: router:
annotations: false annotations: false
httplug:
clients:
wallabag:
factory: Wallabag\Helper\HttpClientFactory
config:
defaults:
timeout: 10
plugins: ['httplug.plugin.logger']
discovery:
client: false
# define custom entity so we can override length attribute to fix utf8mb4 issue # define custom entity so we can override length attribute to fix utf8mb4 issue
craue_config: craue_config:
entity_name: Wallabag\Entity\InternalSetting entity_name: Wallabag\Entity\InternalSetting
@ -467,3 +471,8 @@ craue_config:
when@dev: when@dev:
maker: maker:
root_namespace: 'Wallabag' root_namespace: 'Wallabag'
webpack_encore:
output_path: '%kernel.project_dir%/web/build'
script_attributes:
defer: true

View file

@ -1,10 +1,6 @@
imports: imports:
- { resource: config.yml } - { resource: config.yml }
framework:
assets:
# json_manifest_path: '%kernel.project_dir%/web/bundles/wallabagcore/manifest.json'
#doctrine: #doctrine:
# orm: # orm:
# metadata_cache_driver: apc # metadata_cache_driver: apc

View file

@ -10,7 +10,7 @@ parameters:
framework: framework:
test: ~ test: ~
session: session:
storage_id: session.storage.mock_file storage_factory_id: session.storage.factory.mock_file
profiler: profiler:
collect: false collect: false
translator: translator:

View file

@ -47,8 +47,6 @@ parameters:
from_email: no-reply@wallabag.org from_email: no-reply@wallabag.org
rss_limit: 50
# RabbitMQ processing # RabbitMQ processing
rabbitmq_host: localhost rabbitmq_host: localhost
rabbitmq_port: 5672 rabbitmq_port: 5672
@ -57,7 +55,7 @@ parameters:
rabbitmq_prefetch_count: 10 rabbitmq_prefetch_count: 10
# Redis processing # Redis processing
redis_scheme: tcp redis_scheme: redis
redis_host: localhost redis_host: localhost
redis_port: 6379 redis_port: 6379
redis_path: null redis_path: null

View file

@ -13,6 +13,7 @@ doc-api-json:
homepage: homepage:
path: "/{page}" path: "/{page}"
methods: GET
defaults: defaults:
_controller: 'Wallabag\Controller\EntryController::showUnreadAction' _controller: 'Wallabag\Controller\EntryController::showUnreadAction'
page : 1 page : 1
@ -27,23 +28,27 @@ fos_oauth_server_token:
craue_config_settings_modify: craue_config_settings_modify:
path: /settings path: /settings
methods: [GET, POST]
defaults: defaults:
_controller: 'Craue\ConfigBundle\Controller\SettingsController::modifyAction' _controller: 'Craue\ConfigBundle\Controller\SettingsController::modifyAction'
fos_js_routing: fos_js_routing:
resource: "@FOSJsRoutingBundle/Resources/config/routing/routing.xml" resource: "@FOSJsRoutingBundle/Resources/config/routing/routing-sf4.xml"
2fa_login: 2fa_login:
path: /2fa path: /2fa
methods: GET
defaults: defaults:
_controller: "scheb_two_factor.form_controller:form" _controller: "scheb_two_factor.form_controller:form"
2fa_login_check: 2fa_login_check:
path: /2fa_check path: /2fa_check
methods: POST
# redirect RSS feed to Atom # redirect RSS feed to Atom
rss_to_atom_unread: rss_to_atom_unread:
path: /{username}/{token}/unread.xml path: /{username}/{token}/unread.xml
methods: GET
defaults: defaults:
_controller: 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::redirectAction' _controller: 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::redirectAction'
route: unread_feed route: unread_feed
@ -51,6 +56,7 @@ rss_to_atom_unread:
rss_to_atom_archive: rss_to_atom_archive:
path: /{username}/{token}/archive.xml path: /{username}/{token}/archive.xml
methods: GET
defaults: defaults:
_controller: 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::redirectAction' _controller: 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::redirectAction'
route: archive_feed route: archive_feed
@ -58,6 +64,7 @@ rss_to_atom_archive:
rss_to_atom_starred: rss_to_atom_starred:
path: /{username}/{token}/starred.xml path: /{username}/{token}/starred.xml
methods: GET
defaults: defaults:
_controller: 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::redirectAction' _controller: 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::redirectAction'
route: starred_feed route: starred_feed
@ -65,6 +72,7 @@ rss_to_atom_starred:
rss_to_atom_all: rss_to_atom_all:
path: /{username}/{token}/all.xml path: /{username}/{token}/all.xml
methods: GET
defaults: defaults:
_controller: 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::redirectAction' _controller: 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::redirectAction'
route: all_feed route: all_feed
@ -72,6 +80,7 @@ rss_to_atom_all:
rss_to_atom_tags: rss_to_atom_tags:
path: /{username}/{token}/tags/{slug}.xml path: /{username}/{token}/tags/{slug}.xml
methods: GET
defaults: defaults:
_controller: 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::redirectAction' _controller: 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::redirectAction'
route: tag_feed route: tag_feed

View file

@ -1,5 +1,5 @@
security: security:
encoders: password_hashers:
FOS\UserBundle\Model\UserInterface: sha512 FOS\UserBundle\Model\UserInterface: sha512
role_hierarchy: role_hierarchy:
@ -70,10 +70,9 @@ security:
- { path: /(unread|starred|archive|annotated|all).xml$, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: /(unread|starred|archive|annotated|all).xml$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/locale, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/locale, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: /tags/(.*).xml$, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: /tags/(.*).xml$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/feed, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/feed, roles: PUBLIC_ACCESS }
- { path: /(unread|starred|archive|annotated).xml$, roles: IS_AUTHENTICATED_ANONYMOUSLY } # For backwards compatibility - { path: /(unread|starred|archive|annotated).xml$, roles: IS_AUTHENTICATED_ANONYMOUSLY } # For backwards compatibility
- { path: ^/share, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/share, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/settings, roles: ROLE_SUPER_ADMIN } - { path: ^/settings, roles: ROLE_SUPER_ADMIN }
- { path: ^/annotations, roles: ROLE_USER }
- { path: ^/2fa, role: IS_AUTHENTICATED_2FA_IN_PROGRESS } - { path: ^/2fa, role: IS_AUTHENTICATED_2FA_IN_PROGRESS }
- { path: ^/, roles: ROLE_USER } - { path: ^/, roles: ROLE_USER }

View file

@ -30,6 +30,7 @@ services:
$storeArticleHeaders: '@=service(''craue_config'').get(''store_article_headers'')' $storeArticleHeaders: '@=service(''craue_config'').get(''store_article_headers'')'
$supportUrl: '@=service(''craue_config'').get(''wallabag_support_url'')' $supportUrl: '@=service(''craue_config'').get(''wallabag_support_url'')'
$fonts: '%wallabag.fonts%' $fonts: '%wallabag.fonts%'
$defaultIgnoreOriginInstanceRules: '%wallabag.default_ignore_origin_instance_rules%'
Wallabag\: Wallabag\:
resource: '../../src/*' resource: '../../src/*'
@ -107,6 +108,14 @@ services:
$rabbitMqProducer: '@old_sound_rabbit_mq.import_pocket_html_producer' $rabbitMqProducer: '@old_sound_rabbit_mq.import_pocket_html_producer'
$redisProducer: '@wallabag.producer.redis.pocket_html' $redisProducer: '@wallabag.producer.redis.pocket_html'
Wallabag\Controller\Import\PocketCsvController:
arguments:
$rabbitMqProducer: '@old_sound_rabbit_mq.import_pocket_csv_producer'
$redisProducer: '@wallabag.producer.redis.pocket_csv'
Wallabag\Doctrine\MigrationFactoryDecorator:
decorates: doctrine.migrations.migrations_factory
Doctrine\DBAL\Connection: Doctrine\DBAL\Connection:
alias: doctrine.dbal.default_connection alias: doctrine.dbal.default_connection
@ -187,11 +196,17 @@ services:
tags: tags:
- { name: doctrine.event_subscriber } - { name: doctrine.event_subscriber }
psr18.wallabag.client:
class: Symfony\Component\HttpClient\Psr18Client
arguments:
$client: '@Wallabag\HttpClient\WallabagClient'
Graby\Graby: Graby\Graby:
arguments: arguments:
$config: $config:
error_message: '%wallabag.fetching_error_message%' error_message: '%wallabag.fetching_error_message%'
error_message_title: '%wallabag.fetching_error_message_title%' error_message_title: '%wallabag.fetching_error_message_title%'
$client: '@psr18.wallabag.client'
calls: calls:
- [ setLogger, [ "@logger" ] ] - [ setLogger, [ "@logger" ] ]
tags: tags:
@ -201,9 +216,6 @@ services:
arguments: arguments:
$config: {} $config: {}
wallabag.http_client:
alias: 'httplug.client.wallabag'
Wallabag\SiteConfig\GrabySiteConfigBuilder: Wallabag\SiteConfig\GrabySiteConfigBuilder:
tags: tags:
- { name: monolog.logger, channel: graby } - { name: monolog.logger, channel: graby }
@ -212,11 +224,9 @@ services:
Wallabag\SiteConfig\SiteConfigBuilder: Wallabag\SiteConfig\SiteConfigBuilder:
alias: Wallabag\SiteConfig\GrabySiteConfigBuilder alias: Wallabag\SiteConfig\GrabySiteConfigBuilder
GuzzleHttp\Cookie\CookieJar: ~ Symfony\Component\BrowserKit\HttpBrowser:
arguments:
Wallabag\Helper\HttpClientFactory: $client: '@browser.client'
calls:
- ['addSubscriber', ['@Wallabag\Guzzle\AuthenticatorSubscriber']]
RulerZ\RulerZ: RulerZ\RulerZ:
alias: rulerz alias: rulerz
@ -225,30 +235,17 @@ services:
tags: tags:
- { name: rulerz.operator, target: native, operator: matches } - { name: rulerz.operator, target: native, operator: matches }
Wallabag\Operator\Doctrine\Matches:
tags:
- { name: rulerz.operator, target: doctrine, operator: matches, inline: true }
Wallabag\Operator\PHP\NotMatches: Wallabag\Operator\PHP\NotMatches:
tags: tags:
- { name: rulerz.operator, target: native, operator: notmatches } - { name: rulerz.operator, target: native, operator: notmatches }
Wallabag\Operator\Doctrine\NotMatches:
tags:
- { name: rulerz.operator, target: doctrine, operator: notmatches, inline: true }
Wallabag\Operator\PHP\PatternMatches: Wallabag\Operator\PHP\PatternMatches:
tags: tags:
- { name: rulerz.operator, target: native, operator: "~" } - { name: rulerz.operator, target: native, operator: "~" }
Predis\Client: Predis\Client:
arguments: arguments:
$parameters: $parameters: '%env(REDIS_URL)%'
scheme: '%redis_scheme%'
host: '%redis_host%'
port: '%redis_port%'
path: '%redis_path%'
password: '%redis_password%'
Wallabag\Event\Subscriber\SQLiteCascadeDeleteSubscriber: Wallabag\Event\Subscriber\SQLiteCascadeDeleteSubscriber:
tags: tags:
@ -268,16 +265,6 @@ services:
$defaultSettings: '%wallabag.default_internal_settings%' $defaultSettings: '%wallabag.default_internal_settings%'
$defaultIgnoreOriginInstanceRules: '%wallabag.default_ignore_origin_instance_rules%' $defaultIgnoreOriginInstanceRules: '%wallabag.default_ignore_origin_instance_rules%'
Wallabag\Mailer\UserMailer:
arguments:
$parameters:
template:
confirmation: '%fos_user.registration.confirmation.template%'
resetting: '%fos_user.resetting.email.template%'
from_email:
confirmation: '%fos_user.registration.confirmation.from_email%'
resetting: '%fos_user.resetting.email.from_email%'
Wallabag\Event\Listener\CreateConfigListener: Wallabag\Event\Listener\CreateConfigListener:
arguments: arguments:
$itemsOnPage: "%wallabag.items_on_page%" $itemsOnPage: "%wallabag.items_on_page%"
@ -346,6 +333,10 @@ services:
tags: tags:
- { name: wallabag.import, alias: pocket_html } - { name: wallabag.import, alias: pocket_html }
Wallabag\Import\PocketCsvImport:
tags:
- { name: wallabag.import, alias: pocket_csv }
# to factorize the proximity and bypass translation for prev & next # to factorize the proximity and bypass translation for prev & next
pagerfanta.view.default_wallabag: pagerfanta.view.default_wallabag:
class: Pagerfanta\View\OptionableView class: Pagerfanta\View\OptionableView

View file

@ -20,6 +20,7 @@ services:
$elcuratorConsumer: '@old_sound_rabbit_mq.import_elcurator_consumer' $elcuratorConsumer: '@old_sound_rabbit_mq.import_elcurator_consumer'
$shaarliConsumer: '@old_sound_rabbit_mq.import_shaarli_consumer' $shaarliConsumer: '@old_sound_rabbit_mq.import_shaarli_consumer'
$pocketHtmlConsumer: '@old_sound_rabbit_mq.import_pocket_html_consumer' $pocketHtmlConsumer: '@old_sound_rabbit_mq.import_pocket_html_consumer'
$pocketCsvConsumer: '@old_sound_rabbit_mq.import_pocket_csv_consumer'
$omnivoreConsumer: '@old_sound_rabbit_mq.import_omnivore_consumer' $omnivoreConsumer: '@old_sound_rabbit_mq.import_omnivore_consumer'
wallabag.consumer.amqp.pocket: wallabag.consumer.amqp.pocket:
@ -86,3 +87,8 @@ services:
class: Wallabag\Consumer\AMQPEntryConsumer class: Wallabag\Consumer\AMQPEntryConsumer
arguments: arguments:
$import: '@Wallabag\Import\PocketHtmlImport' $import: '@Wallabag\Import\PocketHtmlImport'
wallabag.consumer.amqp.pocket_csv:
class: Wallabag\Consumer\AMQPEntryConsumer
arguments:
$import: '@Wallabag\Import\PocketCsvImport'

View file

@ -212,3 +212,19 @@ services:
class: Wallabag\Consumer\RedisEntryConsumer class: Wallabag\Consumer\RedisEntryConsumer
arguments: arguments:
$import: '@Wallabag\Import\PocketHtmlImport' $import: '@Wallabag\Import\PocketHtmlImport'
# pocket csv
wallabag.queue.redis.pocket_csv:
class: Simpleue\Queue\RedisQueue
arguments:
$queueName: "wallabag.import.pocket_csv"
wallabag.producer.redis.pocket_csv:
class: Wallabag\Redis\Producer
arguments:
- "@wallabag.queue.redis.pocket_csv"
wallabag.consumer.redis.pocket_csv:
class: Wallabag\Consumer\RedisEntryConsumer
arguments:
$import: '@Wallabag\Import\PocketCsvImport'

View file

@ -6,6 +6,9 @@ services:
# fixtures # fixtures
Wallabag\DataFixtures\: Wallabag\DataFixtures\:
bind:
$defaultIgnoreOriginInstanceRules: '%wallabag.default_ignore_origin_instance_rules%'
$defaultInternalSettings: '%wallabag.default_internal_settings%'
resource: '../../fixtures/*' resource: '../../fixtures/*'
tags: ['doctrine.fixture.orm'] tags: ['doctrine.fixture.orm']
autowire: true autowire: true

View file

@ -1,5 +1,5 @@
parameters: parameters:
wallabag.version: 2.6.10 wallabag.version: 2.7.0-dev
wallabag.paypal_url: "https://liberapay.com/wallabag/donate" wallabag.paypal_url: "https://liberapay.com/wallabag/donate"
wallabag.languages: wallabag.languages:
en: 'English' en: 'English'
@ -18,6 +18,7 @@ parameters:
pt: 'Português' pt: 'Português'
ru: 'Русский' ru: 'Русский'
ja: '日本語' ja: '日本語'
ko: '한국어'
zh: '简体中文' zh: '简体中文'
uk: 'Українська' uk: 'Українська'
hr: 'Hrvatski' hr: 'Hrvatski'
@ -175,5 +176,11 @@ parameters:
- 'Montserrat' - 'Montserrat'
- 'OpenDyslexicRegular' - 'OpenDyslexicRegular'
- 'Oswald' - 'Oswald'
wallabag.allow_mimetypes: ['application/octet-stream', 'application/json', 'text/plain', 'text/csv', 'text/html'] wallabag.allow_mimetypes:
- 'application/octet-stream'
- 'application/json'
- 'text/plain'
- 'text/csv'
- 'text/html'
- 'application/vnd.ms-excel'
wallabag.resource_dir: "%kernel.project_dir%/web/uploads/import" wallabag.resource_dir: "%kernel.project_dir%/web/uploads/import"

View file

@ -1,37 +0,0 @@
const path = require('path');
const webpack = require('webpack');
const StyleLintPlugin = require('stylelint-webpack-plugin');
const projectDir = path.resolve(__dirname, '../../../');
module.exports = {
entry: {
material: path.join(projectDir, './assets/material/index.js'),
public: path.join(projectDir, './assets/_global/share.js'),
},
output: {
filename: '[name].js',
path: path.resolve(projectDir, 'web/wallassets'),
publicPath: '',
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.$': 'jquery',
'window.jQuery': 'jquery',
}),
new StyleLintPlugin({
configFile: 'stylelint.config.js',
failOnError: false,
quiet: false,
context: 'assets',
files: '**/*.scss',
}),
],
resolve: {
alias: {
jquery: path.join(projectDir, 'node_modules/jquery/dist/jquery.js'),
},
},
};

View file

@ -1,58 +0,0 @@
const { merge } = require('webpack-merge');
const ESLintPlugin = require('eslint-webpack-plugin');
const commonConfig = require('./common');
module.exports = merge(commonConfig, {
devtool: 'eval-source-map',
output: {
filename: '[name].dev.js',
},
mode: 'development',
devServer: {
static: {
directory: './web',
},
},
plugins: [
new ESLintPlugin(),
],
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
},
{
test: /\.(s)?css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
},
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['autoprefixer'],
},
},
},
'sass-loader',
],
},
{
test: /\.(jpg|png|gif|svg|ico|eot|ttf|woff|woff2)$/,
type: 'asset/inline',
},
],
},
});

View file

@ -1,98 +0,0 @@
const webpack = require('webpack');
const { merge } = require('webpack-merge');
const ESLintPlugin = require('eslint-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const commonConfig = require('./common');
module.exports = merge(commonConfig, {
output: {
filename: '[name].js',
},
mode: 'production',
devtool: 'source-map',
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
terserOptions: {
output: {
comments: false,
},
},
extractComments: false,
}),
],
},
plugins: [
new ESLintPlugin(),
new MiniCssExtractPlugin(),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production'),
},
}),
new WebpackManifestPlugin({
fileName: 'manifest.json',
sort: (file1, file2) => file1.path.localeCompare(file2.path),
}),
],
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
},
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 1,
},
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['autoprefixer'],
},
},
},
'sass-loader',
],
},
{
test: /\.(jpg|png|gif|svg|ico)$/,
include: /node_modules/,
type: 'asset/resource',
generator: {
filename: 'img/[name][ext]',
},
},
{
test: /\.(jpg|png|gif|svg|ico)$/,
exclude: /node_modules/,
type: 'asset/resource',
},
{
test: /\.(eot|ttf|woff|woff2)$/,
type: 'asset/resource',
generator: {
filename: 'fonts/[name][ext]',
},
},
],
},
});

View file

@ -1,124 +0,0 @@
/* jQuery */
import $ from 'jquery';
/* Annotations */
import annotator from 'annotator';
import ClipboardJS from 'clipboard';
import 'mathjax/es5/tex-svg';
/* Fonts */
import 'material-design-icons-iconfont/dist/material-design-icons.css';
import 'lato-font/css/lato-font.css';
import 'open-dyslexic/open-dyslexic-regular.css';
import '@fontsource/atkinson-hyperlegible';
import '@fontsource/eb-garamond';
import '@fontsource/montserrat';
import '@fontsource/oswald';
import './global.scss';
/* Shortcuts */
import './js/shortcuts/entry';
import './js/shortcuts/main';
/* Highlight */
import './js/highlight';
import { savePercent, retrievePercent } from './js/tools';
/* ==========================================================================
Annotations & Remember position
========================================================================== */
$(document).ready(() => {
if ($('#article').length) {
const app = new annotator.App();
app.include(annotator.ui.main, {
element: document.querySelector('article'),
});
const authorization = {
permits() { return true; },
};
app.registry.registerUtility(authorization, 'authorizationPolicy');
const x = JSON.parse($('#annotationroutes').html());
app.include(annotator.storage.http, $.extend({}, x, {
onError(msg, xhr) {
if (!Object.prototype.hasOwnProperty.call(xhr, 'responseJSON')) {
annotator.notification.banner('An error occurred', 'error');
return;
}
$.each(xhr.responseJSON.children, (k, v) => {
if (v.errors) {
$.each(v.errors, (n, errorText) => {
annotator.notification.banner(errorText, 'error');
});
}
});
},
}));
app.start().then(() => {
app.annotations.load({ entry: x.entryId });
});
$(window).scroll(() => {
const scrollTop = $(window).scrollTop();
const docHeight = $(document).height();
const scrollPercent = (scrollTop) / (docHeight);
const scrollPercentRounded = Math.round(scrollPercent * 100) / 100;
savePercent(x.entryId, scrollPercentRounded);
});
retrievePercent(x.entryId);
$(window).resize(() => {
retrievePercent(x.entryId, true);
});
}
document.querySelectorAll('[data-handler=tag-rename]').forEach((item) => {
const current = item;
current.wallabag_edit_mode = false;
current.onclick = (event) => {
const target = event.currentTarget;
if (target.wallabag_edit_mode === false) {
$(target.parentNode.querySelector('[data-handle=tag-link]')).addClass('hidden');
$(target.parentNode.querySelector('[data-handle=tag-rename-form]')).removeClass('hidden');
target.parentNode.querySelector('[data-handle=tag-rename-form] input').focus();
target.querySelector('.material-icons').innerHTML = 'done';
target.wallabag_edit_mode = true;
} else {
target.parentNode.querySelector('[data-handle=tag-rename-form]').submit();
}
};
});
// mimic radio button because emailTwoFactor is a boolean
$('#update_user_googleTwoFactor').on('change', () => {
$('#update_user_emailTwoFactor').prop('checked', false);
});
$('#update_user_emailTwoFactor').on('change', () => {
$('#update_user_googleTwoFactor').prop('checked', false);
});
// same mimic for super admin
$('#user_googleTwoFactor').on('change', () => {
$('#user_emailTwoFactor').prop('checked', false);
});
$('#user_emailTwoFactor').on('change', () => {
$('#user_googleTwoFactor').prop('checked', false);
});
// handle copy to clipboard for developer stuff
const clipboard = new ClipboardJS('.btn');
clipboard.on('success', (e) => {
e.clearSelection();
});
});

View file

@ -1,4 +0,0 @@
top['bookmarklet-url@wallabag.org'] = '<!DOCTYPE html><html><head><title>bag it!</title>'
+ '<link rel="icon" href="tpl/img/favicon.ico" />'
+ '</head><body><script>window.onload=function(){window.setTimeout'
+ '(function(){history.back();},250);};</script></body></html>';

View file

@ -1,8 +0,0 @@
import 'highlight.js/styles/atom-one-light.css';
import hljs from 'highlight.js';
window.addEventListener('load', () => {
document.querySelectorAll('pre').forEach((element) => {
hljs.highlightElement(element);
});
});

View file

@ -1,15 +0,0 @@
import Mousetrap from 'mousetrap';
/* Shortcuts */
/* Go to */
Mousetrap.bind('g u', () => { window.location.href = Routing.generate('homepage'); });
Mousetrap.bind('g s', () => { window.location.href = Routing.generate('starred'); });
Mousetrap.bind('g r', () => { window.location.href = Routing.generate('archive'); });
Mousetrap.bind('g a', () => { window.location.href = Routing.generate('all'); });
Mousetrap.bind('g t', () => { window.location.href = Routing.generate('tag'); });
Mousetrap.bind('g c', () => { window.location.href = Routing.generate('config'); });
Mousetrap.bind('g i', () => { window.location.href = Routing.generate('import'); });
Mousetrap.bind('g d', () => { window.location.href = Routing.generate('developer'); });
Mousetrap.bind('?', () => { window.location.href = Routing.generate('howto'); });
Mousetrap.bind('g l', () => { window.location.href = Routing.generate('fos_user_security_logout'); });

View file

@ -1,36 +0,0 @@
import $ from 'jquery';
import './shortcuts/main';
import './shortcuts/entry';
/* Allows inline call qr-code call */
import jrQrcode from 'jr-qrcode'; // eslint-disable-line
function supportsLocalStorage() {
try {
return 'localStorage' in window && window.localStorage !== null;
} catch (e) {
return false;
}
}
function savePercent(id, percent) {
if (!supportsLocalStorage()) { return false; }
localStorage[`wallabag.article.${id}.percent`] = percent;
return true;
}
function retrievePercent(id, resized) {
if (!supportsLocalStorage()) { return false; }
const bheight = $(document).height();
const percent = localStorage[`wallabag.article.${id}.percent`];
const scroll = bheight * percent;
if (!resized) {
$('html,body').animate({ scrollTop: scroll }, 'fast');
}
return true;
}
export { savePercent, retrievePercent };

View file

@ -1 +0,0 @@
import './share.scss';

11
assets/bootstrap.js vendored Normal file
View file

@ -0,0 +1,11 @@
import { startStimulusApp } from '@symfony/stimulus-bridge';
// Registers Stimulus controllers from controllers.json and in the controllers/ directory
export default startStimulusApp(require.context(
'@symfony/stimulus-bridge/lazy-controller-loader!./controllers',
true,
/\.[jt]sx?$/,
));
// register any custom, 3rd party controllers here
// app.register('some_controller_name', SomeImportedController);

4
assets/controllers.json Normal file
View file

@ -0,0 +1,4 @@
{
"controllers": [],
"entrypoints": []
}

View file

@ -0,0 +1,13 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['input'];
toggle() {
this.element.classList.toggle('hidden');
if (!this.element.classList.contains('hidden')) {
this.inputTarget.focus();
}
}
}

View file

@ -0,0 +1,57 @@
import { Controller } from '@hotwired/stimulus';
import annotator from 'annotator';
export default class extends Controller {
static values = {
entryId: Number,
createUrl: String,
updateUrl: String,
destroyUrl: String,
searchUrl: String,
};
connect() {
this.app = new annotator.App();
this.app.include(annotator.ui.main, {
element: this.element,
});
const authorization = {
permits() { return true; },
};
this.app.registry.registerUtility(authorization, 'authorizationPolicy');
this.app.include(annotator.storage.http, {
prefix: '',
urls: {
create: this.createUrlValue,
update: this.updateUrlValue,
destroy: this.destroyUrlValue,
search: this.searchUrlValue,
},
entryId: this.entryIdValue,
onError(msg, xhr) {
if (!Object.prototype.hasOwnProperty.call(xhr, 'responseJSON')) {
annotator.notification.banner('An error occurred', 'error');
return;
}
Object.values(xhr.responseJSON.children).forEach((v) => {
if (v.errors) {
Object.values(v.errors).forEach((errorText) => {
annotator.notification.banner(errorText, 'error');
});
}
});
},
});
this.app.start().then(() => {
this.app.annotations.load({ entry: this.entryIdValue });
});
}
disconnect() {
this.app.destroy();
}
}

View file

@ -0,0 +1,15 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['item', 'tagAction'];
toggleSelection(e) {
this.itemTargets.forEach((item) => {
item.checked = e.currentTarget.checked; // eslint-disable-line no-param-reassign
});
}
tagSelection() {
this.element.requestSubmit(this.tagActionTarget);
}
}

View file

@ -0,0 +1,16 @@
import { Controller } from '@hotwired/stimulus';
import ClipboardJS from 'clipboard';
export default class extends Controller {
connect() {
this.clipboard = new ClipboardJS(this.element);
this.clipboard.on('success', (e) => {
e.clearSelection();
});
}
disconnect() {
this.clipboard.destroy();
}
}

View file

@ -0,0 +1,16 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['previewArticle', 'previewContent', 'font', 'fontSize', 'lineHeight', 'maxWidth'];
connect() {
this.updatePreview();
}
updatePreview() {
this.previewArticleTarget.style.maxWidth = `${this.maxWidthTarget.value}em`;
this.previewContentTarget.style.fontFamily = this.fontTarget.value;
this.previewContentTarget.style.fontSize = `${this.fontSizeTarget.value}em`;
this.previewContentTarget.style.lineHeight = `${this.lineHeightTarget.value}em`;
}
}

View file

@ -0,0 +1,39 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
connect() {
this.#choose();
this.mql = window.matchMedia('(prefers-color-scheme: dark)');
this.mql.addEventListener('change', this.#choose.bind(this));
}
useLight() {
this.element.classList.remove('dark-theme');
document.cookie = 'theme=light;samesite=Lax;path=/;max-age=31536000';
}
useDark() {
this.element.classList.add('dark-theme');
document.cookie = 'theme=dark;samesite=Lax;path=/;max-age=31536000';
}
useAuto() {
document.cookie = 'theme=auto;samesite=Lax;path=/;max-age=0';
this.#choose();
}
#choose() {
const themeCookieExists = document.cookie.split(';').some((cookie) => cookie.trim().startsWith('theme='));
if (themeCookieExists) {
return;
}
if (this.mql.matches) {
this.element.classList.add('dark-theme');
} else {
this.element.classList.remove('dark-theme');
}
}
}

View file

@ -0,0 +1,58 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['card', 'paginationWrapper'];
connect() {
this.pagination = this.paginationWrapperTarget.querySelector('.pagination');
this.cardIndex = 0;
this.lastCardIndex = this.cardTargets.length - 1;
/* If we come from next page */
if (window.location.hash === '#prev') {
this.cardIndex = this.lastCardIndex;
}
this.currentCard = this.cardTargets[this.cardIndex];
this.currentCard.classList.add('z-depth-4');
}
selectRightCard() {
if (this.cardIndex >= 0 && this.cardIndex < this.lastCardIndex) {
this.currentCard.classList.remove('z-depth-4');
this.cardIndex += 1;
this.currentCard = this.cardTargets[this.cardIndex];
this.currentCard.classList.add('z-depth-4');
return;
}
if (this.pagination && this.pagination.querySelector('a[rel="next"]')) {
window.location.href = this.pagination.querySelector('a[rel="next"]').href;
}
}
selectLeftCard() {
if (this.cardIndex > 0 && this.cardIndex <= this.lastCardIndex) {
this.currentCard.classList.remove('z-depth-4');
this.cardIndex -= 1;
this.currentCard = this.cardTargets[this.cardIndex];
this.currentCard.classList.add('z-depth-4');
return;
}
if (this.pagination && this.pagination.querySelector('a[rel="prev"]')) {
window.location.href = `${this.pagination.querySelector('a[rel="prev"]').href}#prev`;
}
}
selectCurrentCard() {
const url = this.currentCard.querySelector('a.card-title').href;
if (url) {
window.location.href = url;
}
}
}

View file

@ -0,0 +1,13 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['emailTwoFactor', 'googleTwoFactor'];
uncheckGoogle() {
this.googleTwoFactorTarget.checked = false;
}
uncheckEmail() {
this.emailTwoFactorTarget.checked = false;
}
}

View file

@ -0,0 +1,11 @@
import { Controller } from '@hotwired/stimulus';
import 'highlight.js/styles/atom-one-light.css';
import hljs from 'highlight.js';
export default class extends Controller {
connect() {
this.element.querySelectorAll('pre code').forEach((element) => {
hljs.highlightElement(element);
});
}
}

View file

@ -0,0 +1,7 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
toggleAddTagForm() {
this.dispatch('toggleAddTagForm');
}
}

View file

@ -0,0 +1,16 @@
import { Controller } from '@hotwired/stimulus';
import M from '@materializecss/materialize';
export default class extends Controller {
static values = {
accordion: { type: Boolean, default: true },
};
connect() {
this.instance = M.Collapsible.init(this.element, { accordion: this.accordionValue });
}
disconnect() {
this.instance.destroy();
}
}

View file

@ -0,0 +1,16 @@
import { Controller } from '@hotwired/stimulus';
import M from '@materializecss/materialize';
export default class extends Controller {
connect() {
this.instance = M.Dropdown.init(this.element, {
hover: false,
coverTrigger: false,
constrainWidth: false,
});
}
disconnect() {
this.instance.destroy();
}
}

View file

@ -0,0 +1,32 @@
import { Controller } from '@hotwired/stimulus';
import M from '@materializecss/materialize';
export default class extends Controller {
static values = {
edge: { type: String, default: 'left' },
};
connect() {
this.instance = M.FloatingActionButton.init(this.element);
}
autoDisplay() {
const scrolled = (window.innerHeight + window.scrollY) >= document.body.offsetHeight;
if (scrolled) {
this.toggleScroll = true;
this.instance.open();
} else if (this.toggleScroll === true) {
this.toggleScroll = false;
this.instance.close();
}
}
click() {
this.dispatch('click');
}
disconnect() {
this.instance.destroy();
}
}

View file

@ -0,0 +1,12 @@
import { Controller } from '@hotwired/stimulus';
import M from '@materializecss/materialize';
export default class extends Controller {
connect() {
this.instance = M.FormSelect.init(this.element.querySelector('select'));
}
disconnect() {
this.instance.destroy();
}
}

View file

@ -0,0 +1,24 @@
import { Controller } from '@hotwired/stimulus';
import M from '@materializecss/materialize';
const mobileMaxWidth = 993;
export default class extends Controller {
static values = {
edge: { type: String, default: 'left' },
};
connect() {
this.instance = M.Sidenav.init(this.element, { edge: this.edgeValue });
}
close() {
if (window.innerWidth < mobileMaxWidth) {
this.instance.close();
}
}
disconnect() {
this.instance.destroy();
}
}

View file

@ -0,0 +1,12 @@
import { Controller } from '@hotwired/stimulus';
import M from '@materializecss/materialize';
export default class extends Controller {
connect() {
this.instance = M.Tabs.init(this.element);
}
disconnect() {
this.instance.destroy();
}
}

View file

@ -0,0 +1,12 @@
import { Controller } from '@hotwired/stimulus';
import M from '@materializecss/materialize';
export default class extends Controller {
connect() {
this.instance = M.toast({ text: this.element.innerText });
}
disconnect() {
this.instance.dismissAll();
}
}

View file

@ -0,0 +1,12 @@
import { Controller } from '@hotwired/stimulus';
import M from '@materializecss/materialize';
export default class extends Controller {
connect() {
this.instance = M.Tooltip.init(this.element);
}
disconnect() {
this.instance.destroy();
}
}

View file

@ -0,0 +1,10 @@
import { Controller } from '@hotwired/stimulus';
import jrQrcode from 'jr-qrcode';
export default class extends Controller {
static values = { url: String };
connect() {
this.element.setAttribute('src', jrQrcode.getQrBase64(this.urlValue));
}
}

View file

@ -0,0 +1,10 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
updateWidth() {
const referenceHeight = document.body.offsetHeight - window.innerHeight;
const scrollPercent = (window.scrollY / referenceHeight) * 100;
this.element.style.width = `${scrollPercent}%`;
}
}

View file

@ -0,0 +1,19 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static values = { entryId: Number };
connect() {
window.scrollTo({
top: window.innerHeight * localStorage[`wallabag.article.${this.entryIdValue}.percent`],
behavior: 'smooth',
});
}
saveScroll() {
const scrollPercent = window.scrollY / window.innerHeight;
const scrollPercentRounded = Math.round(scrollPercent * 100) / 100;
localStorage[`wallabag.article.${this.entryIdValue}.percent`] = scrollPercentRounded;
}
}

View file

@ -0,0 +1,141 @@
import { Controller } from '@hotwired/stimulus';
import Mousetrap from 'mousetrap';
export default class extends Controller {
static targets = ['openOriginal', 'markAsFavorite', 'markAsRead', 'deleteEntry', 'showAddUrl', 'showSearch', 'showActions'];
static outlets = ['entries-navigation'];
connect() {
/* Go to */
Mousetrap.bind('g u', () => {
window.location.href = Routing.generate('homepage');
});
Mousetrap.bind('g s', () => {
window.location.href = Routing.generate('starred');
});
Mousetrap.bind('g r', () => {
window.location.href = Routing.generate('archive');
});
Mousetrap.bind('g a', () => {
window.location.href = Routing.generate('all');
});
Mousetrap.bind('g t', () => {
window.location.href = Routing.generate('tag');
});
Mousetrap.bind('g c', () => {
window.location.href = Routing.generate('config');
});
Mousetrap.bind('g i', () => {
window.location.href = Routing.generate('import');
});
Mousetrap.bind('g d', () => {
window.location.href = Routing.generate('developer');
});
Mousetrap.bind('?', () => {
window.location.href = Routing.generate('howto');
});
Mousetrap.bind('g l', () => {
window.location.href = Routing.generate('fos_user_security_logout');
});
/* open original article */
Mousetrap.bind('o', () => {
if (!this.hasOpenOriginalTarget) {
return;
}
this.openOriginalTarget.click();
});
/* mark as favorite */
Mousetrap.bind('f', () => {
if (!this.hasMarkAsFavoriteTarget) {
return;
}
this.markAsFavoriteTarget.click();
});
/* mark as read */
Mousetrap.bind('a', () => {
if (!this.hasMarkAsReadTarget) {
return;
}
this.markAsReadTarget.click();
});
/* delete */
Mousetrap.bind('del', () => {
if (!this.hasDeleteEntryTarget) {
return;
}
this.deleteEntryTarget.click();
});
/* Actions */
Mousetrap.bind('g n', (e) => {
if (!this.hasShowAddUrlTarget) {
return;
}
e.preventDefault();
this.showAddUrlTarget.click();
});
Mousetrap.bind('s', (e) => {
if (!this.hasShowSearchTarget) {
return;
}
e.preventDefault();
this.showSearchTarget.click();
});
Mousetrap.bind('esc', (e) => {
if (!this.hasShowActionsTarget) {
return;
}
e.preventDefault();
this.showActionsTarget.click();
});
const originalStopCallback = Mousetrap.prototype.stopCallback;
Mousetrap.prototype.stopCallback = (e, element, combo) => {
// allow esc key to be used in input fields of topbar
if (combo === 'esc' && element.dataset.topbarTarget !== undefined) {
return false;
}
return originalStopCallback(e, element);
};
Mousetrap.bind('right', () => {
if (!this.hasEntriesNavigationOutlet) {
return;
}
this.entriesNavigationOutlet.selectRightCard();
});
Mousetrap.bind('left', () => {
if (!this.hasEntriesNavigationOutlet) {
return;
}
this.entriesNavigationOutlet.selectLeftCard();
});
Mousetrap.bind('enter', () => {
if (!this.hasEntriesNavigationOutlet) {
return;
}
this.entriesNavigationOutlet.selectCurrentCard();
});
}
}

View file

@ -0,0 +1,7 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
toggle() {
this.element.classList.toggle('entry-nav-top--sticky');
}
}

View file

@ -0,0 +1,12 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['link', 'edit', 'form', 'input'];
showForm() {
this.formTarget.classList.remove('hidden');
this.editTarget.classList.add('hidden');
this.linkTarget.classList.add('hidden');
this.inputTarget.focus();
}
}

View file

@ -0,0 +1,31 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['addUrl', 'addUrlInput', 'search', 'searchInput', 'actions'];
showAddUrl() {
this.actionsTarget.style.display = 'none';
this.addUrlTarget.style.display = 'flex';
this.searchTarget.style.display = 'none';
this.addUrlInputTarget.focus();
}
submittingUrl(e) {
e.currentTarget.disabled = true;
this.addUrlInputTarget.readOnly = true;
this.addUrlInputTarget.blur();
}
showSearch() {
this.actionsTarget.style.display = 'none';
this.addUrlTarget.style.display = 'none';
this.searchTarget.style.display = 'flex';
this.searchInputTarget.focus();
}
showActions() {
this.actionsTarget.style.display = 'flex';
this.addUrlTarget.style.display = 'none';
this.searchTarget.style.display = 'none';
}
}

View file

Before

Width:  |  Height:  |  Size: 891 B

After

Width:  |  Height:  |  Size: 891 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 688 B

After

Width:  |  Height:  |  Size: 688 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 995 B

After

Width:  |  Height:  |  Size: 995 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1,012 B

After

Width:  |  Height:  |  Size: 1,012 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 718 B

After

Width:  |  Height:  |  Size: 718 B

Before After
Before After

19
assets/index.js Executable file
View file

@ -0,0 +1,19 @@
import './bootstrap';
/* Materialize imports */
import '@materializecss/materialize/dist/css/materialize.css';
import '@materializecss/materialize/dist/js/materialize';
import 'mathjax/es5/tex-svg';
/* Fonts */
import 'material-design-icons-iconfont/dist/material-design-icons.css';
import 'lato-font/css/lato-font.css';
import 'open-dyslexic/open-dyslexic-regular.css';
import '@fontsource/atkinson-hyperlegible';
import '@fontsource/eb-garamond';
import '@fontsource/montserrat';
import '@fontsource/oswald';
/* Theme style */
import './scss/index.scss';

View file

@ -1,50 +0,0 @@
/* ==========================================================================
Side-nav
========================================================================== */
.side-nav {
width: 240px;
li {
padding: 0;
&.logo > a:hover {
background: initial;
}
& > a > i.material-icons.theme-toggle-icon {
float: none;
margin-left: 0;
}
}
a {
margin: 0;
}
&.fixed a {
font-size: 13px;
line-height: 44px;
height: 44px;
}
.collapsible-header,
&.fixed .collapsible-header {
height: 45px;
line-height: 44px;
padding: 0 20px;
}
> li.logo {
line-height: 0;
text-align: center;
}
}
.bold > a {
font-weight: bold;
}
.items-number {
float: right;
}

View file

@ -1,263 +0,0 @@
import $ from 'jquery';
/* Materialize imports */
import 'materialize-css/dist/css/materialize.css';
import 'materialize-css/dist/js/materialize';
/* Global imports */
import '../_global/index';
/* Tools */
import {
initExport, initFilters, initRandom, initPreviewText,
} from './js/tools';
/* Import shortcuts */
import './js/shortcuts/main';
import './js/shortcuts/entry';
/* Theme style */
import './css/index.scss';
const mobileMaxWidth = 993;
(function darkTheme() {
const rootEl = document.querySelector('html');
const themeDom = {
darkClass: 'dark-theme',
toggleClass(el) {
return el.classList.toggle(this.darkClass);
},
addClass(el) {
return el.classList.add(this.darkClass);
},
removeClass(el) {
return el.classList.remove(this.darkClass);
},
};
const themeCookie = {
values: {
light: 'light',
dark: 'dark',
},
name: 'theme',
getValue(isDarkTheme) {
return isDarkTheme ? this.values.dark : this.values.light;
},
setCookie(isDarkTheme) {
const value = this.getValue(isDarkTheme);
document.cookie = `${this.name}=${value};samesite=Lax;path=/;max-age=31536000`;
},
removeCookie() {
document.cookie = `${this.name}=auto;samesite=Lax;path=/;max-age=0`;
},
exists() {
return document.cookie.split(';').some((cookie) => cookie.trim().startsWith(`${this.name}=`));
},
};
const preferedColorScheme = {
choose() {
const themeCookieExists = themeCookie.exists();
if (this.isAvailable() && !themeCookieExists) {
const isPreferedColorSchemeDark = window.matchMedia('(prefers-color-scheme: dark)').matches === true;
if (!themeCookieExists) {
themeDom[isPreferedColorSchemeDark ? 'addClass' : 'removeClass'](rootEl);
}
}
},
isAvailable() {
return typeof window.matchMedia === 'function';
},
init() {
if (!this.isAvailable()) {
return false;
}
this.choose();
window.matchMedia('(prefers-color-scheme: dark)').addListener(() => {
this.choose();
});
return true;
},
};
const addDarkThemeListeners = () => {
$(document).ready(() => {
const lightThemeButtons = document.querySelectorAll('.js-theme-toggle[data-theme="light"]');
[...lightThemeButtons].map((lightThemeButton) => {
lightThemeButton.addEventListener('click', (e) => {
e.preventDefault();
themeDom.removeClass(rootEl);
themeCookie.setCookie(false);
});
return true;
});
const darkThemeButtons = document.querySelectorAll('.js-theme-toggle[data-theme="dark"]');
[...darkThemeButtons].map((darkThemeButton) => {
darkThemeButton.addEventListener('click', (e) => {
e.preventDefault();
themeDom.addClass(rootEl);
themeCookie.setCookie(true);
});
return true;
});
const autoThemeButtons = document.querySelectorAll('.js-theme-toggle[data-theme="auto"]');
[...autoThemeButtons].map((autoThemeButton) => {
autoThemeButton.addEventListener('click', (e) => {
e.preventDefault();
themeCookie.removeCookie();
preferedColorScheme.choose();
});
return true;
});
});
};
preferedColorScheme.init();
addDarkThemeListeners();
}());
const stickyNav = () => {
const nav = $('.js-entry-nav-top');
$('[data-toggle="actions"]').click(() => {
nav.toggleClass('entry-nav-top--sticky');
});
};
const articleScroll = () => {
const articleEl = $('#article');
if (articleEl.length > 0) {
$(window).scroll(() => {
const s = $(window).scrollTop();
const d = $(document).height();
const c = $(window).height();
const articleElBottom = articleEl.offset().top + articleEl.height();
const scrollPercent = (s / (d - c)) * 100;
$('.progress .determinate').css('width', `${scrollPercent}%`);
const fixedActionBtn = $('.js-fixed-action-btn');
const toggleScrollDataName = 'toggle-auto';
if ((s + c) > articleElBottom) {
fixedActionBtn.data(toggleScrollDataName, true);
fixedActionBtn.openFAB();
} else if (fixedActionBtn.data(toggleScrollDataName) === true) {
fixedActionBtn.data(toggleScrollDataName, false);
fixedActionBtn.closeFAB();
}
});
}
};
$(document).ready(() => {
// sideNav
$('.button-collapse').sideNav();
$('select').material_select();
$('.collapsible').collapsible({
accordion: false,
});
$('.datepicker').pickadate({
selectMonths: true,
selectYears: 15,
formatSubmit: 'yyyy-mm-dd',
hiddenName: false,
format: 'yyyy-mm-dd',
container: 'body',
});
$('.dropdown-trigger').dropdown({ hover: false });
initFilters();
initExport();
initRandom();
stickyNav();
articleScroll();
initPreviewText();
const toggleNav = (toShow, toFocus) => {
$('.nav-panel-actions').hide(100);
$(toShow).show(100);
$(toFocus).focus();
};
$('#nav-btn-add-tag').on('click', () => {
$('.nav-panel-add-tag').toggle(100);
$('.nav-panel-menu').addClass('hidden');
if (window.innerWidth < mobileMaxWidth) {
$('.side-nav').sideNav('hide');
}
$('#tag_label').focus();
return false;
});
$('#nav-btn-add').on('click', () => {
toggleNav('.nav-panel-add', '#entry_url');
return false;
});
$('#config_fontsize').on('input', () => {
const value = $('#config_fontsize').val();
const css = `${value}em`;
$('#preview-content').css('font-size', css);
});
$('#config_font').on('change', () => {
const value = $('#config_font').val();
$('#preview-content').css('font-family', value);
});
$('#config_lineHeight').on('input', () => {
const value = $('#config_lineHeight').val();
const css = `${value}em`;
$('#preview-content').css('line-height', css);
});
$('#config_maxWidth').on('input', () => {
const value = $('#config_maxWidth').val();
const css = `${value}em`;
$('#preview-article').css('max-width', css);
});
const materialAddForm = $('.nav-panel-add');
materialAddForm.on('submit', () => {
materialAddForm.addClass('disabled');
$('input#entry_url', materialAddForm).prop('readonly', true).trigger('blur');
});
$('#nav-btn-search').on('click', () => {
toggleNav('.nav-panel-search', '#search_entry_term');
return false;
});
$('.close').on('click', (e) => {
$(e.target).parent('.nav-panel-item').hide(100);
$('.nav-panel-actions').show(100);
return false;
});
const mainCheckboxes = document.querySelectorAll('[data-js="checkboxes-toggle"]');
if (mainCheckboxes.length) {
[...mainCheckboxes].forEach((el) => {
el.addEventListener('click', () => {
const checkboxes = document.querySelectorAll(el.dataset.toggle);
[...checkboxes].forEach((checkbox) => {
const checkboxClone = checkbox;
checkboxClone.checked = el.checked;
});
});
});
}
$('form[name="form_mass_action"] input[name="tags"]').on('keydown', (e) => {
if (e.key === 'Enter') {
e.preventDefault();
$('form[name="form_mass_action"] button[name="tag"]').trigger('click');
}
});
});

View file

@ -1,26 +0,0 @@
import Mousetrap from 'mousetrap';
import $ from 'jquery';
$(document).ready(() => {
if ($('#article').length > 0) {
/* open original article */
Mousetrap.bind('o', () => {
$('ul.side-nav a.original i')[0].click();
});
/* mark as favorite */
Mousetrap.bind('f', () => {
$('ul.side-nav a.favorite i')[0].click();
});
/* mark as read */
Mousetrap.bind('a', () => {
$('ul.side-nav a.markasread i')[0].click();
});
/* delete */
Mousetrap.bind('del', () => {
$('ul.side-nav a.delete i')[0].click();
});
}
});

View file

@ -1,92 +0,0 @@
import Mousetrap from 'mousetrap';
import $ from 'jquery';
function toggleFocus(cardToToogleFocus) {
if (cardToToogleFocus) {
$(cardToToogleFocus).toggleClass('z-depth-4');
}
}
$(document).ready(() => {
const cards = $('#content').find('.card');
const cardNumber = cards.length;
let cardIndex = 0;
/* If we come from next page */
if (window.location.hash === '#prev') {
cardIndex = cardNumber - 1;
}
let card = cards[cardIndex];
const pagination = $('.pagination');
/* Show nothing on quickstart */
if ($('#content > div.quickstart').length > 0) {
return;
}
/* Show nothing on login/register page */
if ($('#username').length > 0 || $('#fos_user_registration_form_username').length > 0) {
return;
}
/* Show nothing on login/register page */
if ($('#username').length > 0 || $('#fos_user_registration_form_username').length > 0) {
return;
}
/* Focus current card */
toggleFocus(card);
/* Actions */
Mousetrap.bind('g n', () => {
$('#nav-btn-add').trigger('click');
return false;
});
Mousetrap.bind('s', () => {
$('#nav-btn-search').trigger('click');
return false;
});
Mousetrap.bind('esc', () => {
$('.close').trigger('click');
});
/* Select right card. If there's a next page, go to next page */
Mousetrap.bind('right', () => {
if (cardIndex >= 0 && cardIndex < cardNumber - 1) {
toggleFocus(card);
cardIndex += 1;
card = cards[cardIndex];
toggleFocus(card);
return;
}
if (pagination.length > 0 && pagination.find('li.next:not(.disabled)').length > 0 && cardIndex === cardNumber - 1) {
window.location.href = window.location.origin + $(pagination).find('li.next a').attr('href');
}
});
/* Select previous card. If there's a previous page, go to next page */
Mousetrap.bind('left', () => {
if (cardIndex > 0 && cardIndex < cardNumber) {
toggleFocus(card);
cardIndex -= 1;
card = cards[cardIndex];
toggleFocus(card);
return;
}
if (pagination.length > 0 && $(pagination).find('li.prev:not(.disabled)').length > 0 && cardIndex === 0) {
window.location.href = `${window.location.origin + $(pagination).find('li.prev a').attr('href')}#prev`;
}
});
Mousetrap.bind('enter', () => {
if (typeof card !== 'object') {
return;
}
const url = $(card).find('.card-title a').attr('href');
if (typeof url === 'string' && url.length > 0) {
window.location.href = window.location.origin + url;
}
});
});

View file

@ -1,53 +0,0 @@
import $ from 'jquery';
function initFilters() {
// no display if filters not available
if ($('div').is('#filters')) {
$('#button_filters').show();
$('.js-filters-action').sideNav({ edge: 'right' });
$('#clear_form_filters').on('click', () => {
$('#filters input').val('');
$('#filters :checked').removeAttr('checked');
return false;
});
}
}
function initExport() {
// no display if export not available
if ($('div').is('#export')) {
$('#button_export').show();
$('.js-export-action').sideNav({ edge: 'right' });
}
}
function initRandom() {
// no display if export (ie: entries) not available
if ($('div').is('#export')) {
$('#button_random').show();
}
}
function initPreviewText() {
// no display if preview_text not available
if ($('div').is('#preview-article')) {
const defaultFontFamily = $('#config_font').val();
const defaultFontSize = $('#config_fontsize').val();
const defaultLineHeight = $('#config_lineHeight').val();
const defaultMaxWidth = $('#config_maxWidth').val();
const previewContent = $('#preview-content');
previewContent.css('font-family', defaultFontFamily);
previewContent.css('font-size', `${defaultFontSize}em`);
previewContent.css('line-height', `${defaultLineHeight}em`);
$('#preview-article').css('max-width', `${defaultMaxWidth}em`);
}
}
export {
initExport,
initFilters,
initRandom,
initPreviewText,
};

View file

@ -154,6 +154,15 @@ a.original:not(.waves-effect) {
} }
} }
.card .card-content .card-title,
.card-stacked .card-content .card-title {
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.card-entry-labels li, .card-entry-labels li,
.card-tag-labels li { .card-tag-labels li {
margin: 10px 10px 10px auto; margin: 10px 10px 10px auto;
@ -179,6 +188,7 @@ a.original:not(.waves-effect) {
.card-entry-tags a, .card-entry-tags a,
.card-entry-labels a, .card-entry-labels a,
.card-tag-labels a, .card-tag-labels a,
.card-tag-labels button,
.card-entry-labels-hidden a, .card-entry-labels-hidden a,
#list .chip a { #list .chip a {
text-decoration: none; text-decoration: none;
@ -186,6 +196,14 @@ a.original:not(.waves-effect) {
color: #fff; color: #fff;
} }
.card-tag-labels button {
background: transparent;
border: none;
font-weight: normal;
color: #fff;
cursor: pointer;
}
.card-tag-link { .card-tag-link {
width: calc(100% - 24px); width: calc(100% - 24px);
line-height: 1.3; line-height: 1.3;
@ -196,6 +214,7 @@ a.original:not(.waves-effect) {
.card-tag-form { .card-tag-form {
display: flex; display: flex;
align-items: center;
min-width: 100px; min-width: 100px;
flex-grow: 1; flex-grow: 1;
} }

View file

@ -12,9 +12,9 @@
.collapsible-header, .collapsible-header,
.collection, .collection,
.dropdown-content, .dropdown-content,
.side-nav, .sidenav,
.side-nav .collapsible-body, .sidenav .collapsible-body,
.side-nav.fixed .collapsible-body, .sidenav.sidenav-fixed .collapsible-body,
.tabs { .tabs {
background-color: #131716; background-color: #131716;
} }
@ -59,10 +59,13 @@
#article article h5, #article article h5,
#article article h6, #article article h6,
.dropdown-content li > a, .dropdown-content li > a,
.nav-panels .input-field input:focus, .input-field input,
.input-field input:focus,
.results-item, .results-item,
.side-nav li > a, .sidenav li > a,
.side-nav li > a > i.material-icons { .sidenav li > a > i.material-icons,
.sidenav li button,
.sidenav li button > i.material-icons {
color: #dfdfdf; color: #dfdfdf;
} }
@ -81,14 +84,15 @@
color: #dfdfdf !important; color: #dfdfdf !important;
} }
.side-nav li.active { .sidenav li.active {
background-color: #2f2f2f; background-color: #2f2f2f;
} }
.mass-action-tags .mass-action-tags-input.mass-action-tags-input, .mass-action-tags .mass-action-tags-input.mass-action-tags-input,
.side-nav li:not(.logo) > a:hover, .sidenav li:not(.logo) > a:hover,
.side-nav .collapsible-header:hover, .sidenav li:not(.logo) button:hover,
.side-nav.fixed .collapsible-header:hover { .sidenav .collapsible-header:hover,
.sidenav.sidenav-fixed .collapsible-header:hover {
background-color: #1d1d1d; background-color: #1d1d1d;
} }
@ -141,6 +145,12 @@
background-color: transparent; background-color: transparent;
} }
.z-depth-4 {
box-shadow: 0 16px 24px 2px rgba(255 255 255 / 14%),
0 6px 30px 5px rgba(255 255 255 / 12%),
0 8px 10px -7px rgba(255 255 255 / 20%);
}
@media only screen and (min-width: 992px) { @media only screen and (min-width: 992px) {
#article { #article {
background-color: #101010; background-color: #101010;

View file

@ -125,24 +125,24 @@ a.icon-image {
} }
&.diaspora::before { &.diaspora::before {
background: url("../../_global/img/icons/diaspora-icon--black.png") no-repeat center/80%; background: url("../img/icons/diaspora-icon--black.png") no-repeat center/80%;
} }
&.unmark::before { &.unmark::before {
background: url("../../_global/img/icons/unmark-icon--black.png") no-repeat center/80%; background: url("../img/icons/unmark-icon--black.png") no-repeat center/80%;
} }
&.linkding::before { &.linkding::before {
background: url("../../_global/img/icons/linkding.svg") no-repeat center/80%; background: url("../img/icons/linkding.svg") no-repeat center/80%;
filter: grayscale(1); filter: grayscale(1);
} }
&.shaarli::before { &.shaarli::before {
background: url("../../_global/img/icons/shaarli.png") no-repeat center/80%; background: url("../img/icons/shaarli.png") no-repeat center/80%;
} }
&.scuttle::before { &.scuttle::before {
background: url("../../_global/img/icons/scuttle.png") no-repeat center/80%; background: url("../img/icons/scuttle.png") no-repeat center/80%;
} }
} }

View file

@ -6,17 +6,38 @@ nav {
line-height: initial; line-height: initial;
} }
// adapted from anchor styles from node_modules/@materializecss/materialize/sass/components/_navbar.scss
nav ul button {
transition: background-color .3s;
font-size: 1rem;
color: #fff;
display: block;
padding: 0 15px;
cursor: pointer;
background: none;
border: 0;
&:focus {
background: none;
}
&:hover {
background-color: rgba(0 0 0 / 10%);
}
}
nav { nav {
input { input {
color: #aaa; color: #aaa;
} }
ul button:hover,
ul a:hover { ul a:hover {
background-color: initial; background-color: initial;
} }
} }
.nav-panel-item .button-collapse { .nav-panel-item .sidenav-trigger {
margin-left: 0; margin-left: 0;
margin-right: 0.5rem; margin-right: 0.5rem;
padding-left: 0.5rem; padding-left: 0.5rem;
@ -34,6 +55,7 @@ nav {
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
button,
a { a {
padding: 10px 15px; padding: 10px 15px;
} }
@ -143,14 +165,6 @@ nav {
margin: 0 1%; margin: 0 1%;
} }
.button-filters {
display: none;
}
.button-export {
display: none;
}
.entry-nav-top--sticky { .entry-nav-top--sticky {
position: sticky; position: sticky;
top: 0; top: 0;
@ -183,7 +197,7 @@ nav {
justify-content: end; justify-content: end;
} }
.button-collapse { .sidenav-trigger {
display: none; display: none;
} }

85
assets/scss/_sidenav.scss Normal file
View file

@ -0,0 +1,85 @@
/* ==========================================================================
Sidenav
========================================================================== */
.sidenav {
width: 240px;
li {
padding: 0;
&.logo > a:hover {
background: initial;
}
& button > i.material-icons.theme-toggle-icon,
& > a > i.material-icons.theme-toggle-icon {
float: none;
margin-left: 0;
}
}
a {
margin: 0;
}
&.sidenav-fixed button,
&.sidenav-fixed a {
font-size: 13px;
line-height: 44px;
height: 44px;
}
.collapsible-header,
&.sidenav-fixed .collapsible-header {
height: 45px;
line-height: 44px;
padding: 0 20px;
}
> li.logo {
line-height: 0;
text-align: center;
}
}
// adapted from anchor styles from node_modules/@materializecss/materialize/sass/components/_sidenav.scss
.sidenav li button {
color: rgba(0 0 0 / 87%);
display: block;
font-size: 14px;
font-weight: 500;
height: 48px;
line-height: 48px;
padding: 0 (16px * 2);
width: 100%;
text-align: left;
&:hover {
background-color: rgba(0 0 0 / 5%);
}
& > i,
& > i.material-icons {
float: left;
height: 48px;
line-height: 48px;
margin: 0 (16px * 2) 0 0;
width: 24px;
color: rgba(0 0 0 / 54%);
}
}
.bold > a,
.bold > button {
font-weight: bold;
}
.items-number {
float: right;
}
.button-filters .sidenav-trigger,
.button-export .sidenav-trigger {
display: block;
}

View file

@ -1,3 +1,5 @@
@use "variables";
/* ========================================================================== /* ==========================================================================
* Various * Various
* ========================================================================== */ * ========================================================================== */
@ -38,3 +40,18 @@ nav .input-field input {
.tab { .tab {
flex: 1; flex: 1;
} }
.btn-link {
background: none;
border: 0;
padding: 0;
color: variables.$blue-accent-color;
&:focus {
background: none;
}
}
.inline-block {
display: inline-block;
}

View file

@ -1,3 +1,4 @@
@use "material-icons";
@use "variables"; @use "variables";
/* Style */ /* Style */

1
assets/share.js Normal file
View file

@ -0,0 +1 @@
import './scss/share.scss';

View file

@ -5,8 +5,9 @@ use ShipMonk\ComposerDependencyAnalyser\Config\ErrorType;
$config = new Configuration(); $config = new Configuration();
return $config $config
->disableComposerAutoloadPathScan() ->disableComposerAutoloadPathScan()
->disableExtensionsAnalysis()
->enableAnalysisOfUnusedDevDependencies() ->enableAnalysisOfUnusedDevDependencies()
->addPathToScan(__DIR__ . '/app', false) ->addPathToScan(__DIR__ . '/app', false)
->addPathToScan(__DIR__ . '/migrations', false) ->addPathToScan(__DIR__ . '/migrations', false)
@ -22,14 +23,13 @@ return $config
'friendsoftwig/twigcs', 'friendsoftwig/twigcs',
'incenteev/composer-parameter-handler', 'incenteev/composer-parameter-handler',
'j0k3r/graby-site-config', 'j0k3r/graby-site-config',
'j0k3r/php-readability',
'laminas/laminas-code', 'laminas/laminas-code',
'lcobucci/jwt', 'lcobucci/jwt',
'mgargano/simplehtmldom', 'mgargano/simplehtmldom',
'mnapoli/piwik-twig-extension', 'mnapoli/piwik-twig-extension',
'ocramius/proxy-manager', 'ocramius/proxy-manager',
'pagerfanta/twig', 'pagerfanta/twig',
'php-http/client-common',
'php-http/httplug',
'php-http/mock-client', 'php-http/mock-client',
'phpstan/extension-installer', 'phpstan/extension-installer',
'phpstan/phpstan', 'phpstan/phpstan',
@ -38,30 +38,22 @@ return $config
'phpstan/phpstan-symfony', 'phpstan/phpstan-symfony',
'psr/http-client', 'psr/http-client',
'psr/http-factory', 'psr/http-factory',
'psr/http-message', 'rector/rector',
'rulerz-php/doctrine-orm',
'scheb/2fa-qr-code',
'scheb/2fa-trusted-device', 'scheb/2fa-trusted-device',
'shipmonk/composer-dependency-analyser', 'shipmonk/composer-dependency-analyser',
'symfony/asset', 'symfony/asset',
'symfony/browser-kit',
'symfony/css-selector', 'symfony/css-selector',
'symfony/doctrine-bridge',
'symfony/google-mailer', 'symfony/google-mailer',
'symfony/intl', 'symfony/intl',
'symfony/phpunit-bridge', 'symfony/phpunit-bridge',
'symfony/polyfill-php80',
'symfony/polyfill-php81',
'symfony/proxy-manager-bridge', 'symfony/proxy-manager-bridge',
'symfony/templating', 'symfony/templating',
'symfony/var-dumper', 'symfony/var-dumper',
'twig/string-extra', 'twig/string-extra',
], [ErrorType::UNUSED_DEPENDENCY]) ], [ErrorType::UNUSED_DEPENDENCY])
->ignoreErrorsOnPackages([ ->ignoreErrorsOnPackages([
'guzzlehttp/streams',
'monolog/monolog', 'monolog/monolog',
'symfony/filesystem', 'symfony/filesystem',
'symfony/http-client',
], [ErrorType::PROD_DEPENDENCY_ONLY_IN_DEV]) ], [ErrorType::PROD_DEPENDENCY_ONLY_IN_DEV])
->ignoreErrorsOnPackages([ ->ignoreErrorsOnPackages([
'dama/doctrine-test-bundle', 'dama/doctrine-test-bundle',
@ -71,4 +63,9 @@ return $config
'symfony/web-profiler-bundle', 'symfony/web-profiler-bundle',
'symfony/web-server-bundle', 'symfony/web-server-bundle',
], [ErrorType::DEV_DEPENDENCY_IN_PROD]) ], [ErrorType::DEV_DEPENDENCY_IN_PROD])
->ignoreErrorsOnPackages([
'gedmo/doctrine-extensions',
], [ErrorType::SHADOW_DEPENDENCY])
; ;
return $config;

View file

@ -38,7 +38,7 @@
"issues": "https://github.com/wallabag/wallabag/issues" "issues": "https://github.com/wallabag/wallabag/issues"
}, },
"require": { "require": {
"php": ">=7.4", "php": ">=8.2",
"ext-ctype": "*", "ext-ctype": "*",
"ext-curl": "*", "ext-curl": "*",
"ext-dom": "*", "ext-dom": "*",
@ -57,141 +57,147 @@
"ext-tidy": "*", "ext-tidy": "*",
"ext-tokenizer": "*", "ext-tokenizer": "*",
"ext-xml": "*", "ext-xml": "*",
"babdev/pagerfanta-bundle": "^3.8", "babdev/pagerfanta-bundle": "^4.5",
"craue/config-bundle": "^2.7.0", "craue/config-bundle": "^2.7.0",
"defuse/php-encryption": "^2.4", "defuse/php-encryption": "^2.4",
"doctrine/collections": "^1.8", "doctrine/collections": "^2.3",
"doctrine/common": "^3.4.3", "doctrine/common": "^3.5.0",
"doctrine/dbal": "^3.8.2", "doctrine/dbal": "^3.9.4",
"doctrine/doctrine-bundle": "^2.11.3", "doctrine/doctrine-bundle": "^2.13.2",
"doctrine/doctrine-migrations-bundle": "^3.3", "doctrine/doctrine-migrations-bundle": "^3.4.1",
"doctrine/event-manager": "^1.2", "doctrine/event-manager": "^1.2",
"doctrine/migrations": "^3.5.5", "doctrine/migrations": "^3.8.2",
"doctrine/orm": "^2.18.1", "doctrine/orm": "^2.20.2",
"doctrine/persistence": "^3.2", "doctrine/persistence": "^3.4",
"egulias/email-validator": "^3.2.6", "egulias/email-validator": "^4.0.4",
"enshrined/svg-sanitize": "^0.21", "enshrined/svg-sanitize": "^0.22",
"friendsofsymfony/jsrouting-bundle": "^2.8", "friendsofsymfony/jsrouting-bundle": "^3.5",
"friendsofsymfony/oauth-server-bundle": "dev-master#dc8ff343363cf794d30eb1a123610d186a43f162", "friendsofsymfony/oauth-server-bundle": "dev-master#dc8ff343363cf794d30eb1a123610d186a43f162",
"friendsofsymfony/rest-bundle": "^3.6", "friendsofsymfony/rest-bundle": "^3.8",
"friendsofsymfony/user-bundle": "^3.2.1", "friendsofsymfony/user-bundle": "^3.4.0",
"guzzlehttp/guzzle": "^5.3.4", "guzzlehttp/psr7": "^2.7.0",
"guzzlehttp/psr7": "^2.6.2", "html2text/html2text": "^4.3.2",
"guzzlehttp/streams": "^3.0",
"html2text/html2text": "^4.3.1",
"incenteev/composer-parameter-handler": "^2.2", "incenteev/composer-parameter-handler": "^2.2",
"j0k3r/graby": "^2.4.5", "j0k3r/graby": "^2.4.6",
"j0k3r/graby-site-config": "^1.0", "j0k3r/graby-site-config": "^1.0.197",
"j0k3r/php-readability": "^1.2.13",
"javibravo/simpleue": "^2.1", "javibravo/simpleue": "^2.1",
"jms/serializer": "^3.29.1", "jms/serializer": "^3.32.3",
"jms/serializer-bundle": "^5.4", "jms/serializer-bundle": "^5.5.1",
"laminas/laminas-code": "^4.7.1", "laminas/laminas-code": "^4.16",
"lcobucci/jwt": "^4.3", "lcobucci/jwt": "^4.3",
"league/html-to-markdown": "^5.1", "league/html-to-markdown": "^5.1.1",
"mgargano/simplehtmldom": "^1.5", "mgargano/simplehtmldom": "^1.5",
"mnapoli/piwik-twig-extension": "^3.0", "mnapoli/piwik-twig-extension": "^3.0",
"monolog/monolog": "^2.9", "monolog/monolog": "^2.10",
"nelmio/api-doc-bundle": "^4.20.0", "nelmio/api-doc-bundle": "^4.38.1",
"nelmio/cors-bundle": "^2.4", "nelmio/cors-bundle": "^2.5",
"ocramius/proxy-manager": "^2.1.1", "ocramius/proxy-manager": "^2.1.1",
"pagerfanta/core": "^3.8", "pagerfanta/core": "^3.8",
"pagerfanta/doctrine-orm-adapter": "^3.8", "pagerfanta/doctrine-orm-adapter": "^4.7",
"pagerfanta/twig": "^3.8", "pagerfanta/twig": "^4.7",
"php-amqplib/php-amqplib": "^3.6.1", "php-amqplib/php-amqplib": "^3.7.3",
"php-amqplib/rabbitmq-bundle": "^2.14.0", "php-amqplib/rabbitmq-bundle": "^2.17.3",
"php-http/client-common": "^2.7.1",
"php-http/guzzle5-adapter": "^2.0",
"php-http/httplug": "^2.4",
"php-http/httplug-bundle": "^1.32",
"pragmarx/recovery": "^0.2.1", "pragmarx/recovery": "^0.2.1",
"predis/predis": "^2.2.2", "predis/predis": "^3.2.0",
"psr/http-client": "^1.0.3", "psr/http-client": "^1.0.3",
"psr/http-factory": "^1.0.2", "psr/http-factory": "^1.1.0",
"psr/http-message": "^2.0", "psr/http-message": "^2.0",
"psr/log": "^1.1.4", "psr/log": "^1.1.4",
"rulerz-php/doctrine-orm": "dev-master",
"scheb/2fa-backup-code": "^5.13.2", "scheb/2fa-backup-code": "^5.13.2",
"scheb/2fa-bundle": "^5.13.2", "scheb/2fa-bundle": "^5.13.2",
"scheb/2fa-email": "^5.13.2", "scheb/2fa-email": "^5.13.2",
"scheb/2fa-google-authenticator": "^5.13.2", "scheb/2fa-google-authenticator": "^5.13.2",
"scheb/2fa-qr-code": "^5.13.2",
"scheb/2fa-trusted-device": "^5.13.2", "scheb/2fa-trusted-device": "^5.13.2",
"scssphp/scssphp": "^1.12.1", "scssphp/scssphp": "^2.0.1",
"sensio/framework-extra-bundle": "^6.2.10", "sensio/framework-extra-bundle": "^6.2.10",
"sentry/sentry-symfony": "^5.0.1", "sentry/sentry-symfony": "^5.2.0",
"spiriitlabs/form-filter-bundle": "^10.0", "spiriitlabs/form-filter-bundle": "^10.0.2",
"stof/doctrine-extensions-bundle": "^1.11.0", "stof/doctrine-extensions-bundle": "^1.13.0",
"symfony/asset": "^5.4.35", "symfony/asset": "^5.4.45",
"symfony/config": "^5.4.35", "symfony/browser-kit": "^5.4.45",
"symfony/console": "^5.4.35", "symfony/config": "^5.4.46",
"symfony/dependency-injection": "^5.4.35", "symfony/console": "^5.4.47",
"symfony/doctrine-bridge": "^5.4.35", "symfony/dependency-injection": "^5.4.48",
"symfony/dom-crawler": "^5.4.35", "symfony/doctrine-bridge": "^5.4.48",
"symfony/error-handler": "^5.4.35", "symfony/dom-crawler": "^5.4.48",
"symfony/event-dispatcher": "^5.4.35", "symfony/error-handler": "^5.4.46",
"symfony/event-dispatcher-contracts": "^2.5.2", "symfony/event-dispatcher": "^5.4.45",
"symfony/expression-language": "^5.4.35", "symfony/event-dispatcher-contracts": "^2.5.4",
"symfony/filesystem": "^5.4", "symfony/expression-language": "^5.4.45",
"symfony/finder": "^5.4.35", "symfony/filesystem": "^5.4.45",
"symfony/form": "^5.4.35", "symfony/finder": "^5.4.45",
"symfony/framework-bundle": "^5.4.35", "symfony/form": "^5.4.45",
"symfony/google-mailer": "^5.4.35", "symfony/framework-bundle": "^5.4.45",
"symfony/http-client": "^5.4.35", "symfony/google-mailer": "^5.4.45",
"symfony/http-client-contracts": "^2.5", "symfony/http-client": "^5.4.49",
"symfony/http-foundation": "^5.4.35", "symfony/http-client-contracts": "^2.5.5",
"symfony/http-kernel": "^5.4.35", "symfony/http-foundation": "^5.4.48",
"symfony/intl": "^5.4.35", "symfony/http-kernel": "^5.4.48",
"symfony/mailer": "^5.4.35", "symfony/intl": "^5.4.47",
"symfony/mime": "^5.4.35", "symfony/mailer": "^5.4.45",
"symfony/mime": "^5.4.45",
"symfony/monolog-bundle": "^3.10", "symfony/monolog-bundle": "^3.10",
"symfony/options-resolver": "^5.4.21", "symfony/options-resolver": "^5.4.45",
"symfony/polyfill-php80": "^1.29", "symfony/proxy-manager-bridge": "^5.4.45",
"symfony/polyfill-php81": "^1.29", "symfony/routing": "^5.4.48",
"symfony/proxy-manager-bridge": "^5.4.21", "symfony/security-bundle": "^5.4.45",
"symfony/routing": "^5.4.35", "symfony/security-core": "^5.4.48",
"symfony/security-bundle": "^5.4.35", "symfony/security-http": "^5.4.47",
"symfony/security-core": "^5.4.35", "symfony/templating": "^5.4.45",
"symfony/security-http": "^5.4.35", "symfony/translation-contracts": "^2.5.4",
"symfony/templating": "^5.4.35", "symfony/twig-bundle": "^5.4.45",
"symfony/translation-contracts": "^2.5.2", "symfony/validator": "^5.4.48",
"symfony/twig-bundle": "^5.4.35", "symfony/webpack-encore-bundle": "^1.17.2",
"symfony/validator": "^5.4.35", "tecnickcom/tcpdf": "^6.8.2",
"tecnickcom/tcpdf": "^6.6.5", "twig/extra-bundle": "^3.20",
"twig/extra-bundle": "^3.8", "twig/string-extra": "^3.20",
"twig/string-extra": "^3.8", "twig/twig": "^3.20.0",
"twig/twig": "^3.8.0",
"wallabag/phpepub": "^4.0.10", "wallabag/phpepub": "^4.0.10",
"wallabag/rulerz": "dev-master", "wallabag/rulerz": "dev-master",
"wallabag/rulerz-bundle": "dev-master", "wallabag/rulerz-bundle": "dev-master",
"willdurand/hateoas": "^3.10", "willdurand/hateoas": "^3.12",
"willdurand/hateoas-bundle": "^2.6" "willdurand/hateoas-bundle": "^2.7"
}, },
"require-dev": { "require-dev": {
"dama/doctrine-test-bundle": "^8.0.2", "dama/doctrine-test-bundle": "^8.2.2",
"doctrine/data-fixtures": "^1.7", "doctrine/data-fixtures": "^2.0.2",
"doctrine/doctrine-fixtures-bundle": "^3.5.1", "doctrine/doctrine-fixtures-bundle": "^3.7.1",
"ergebnis/composer-normalize": "^2.42.0", "ergebnis/composer-normalize": "^2.45.0",
"friendsofphp/php-cs-fixer": "^3.49", "friendsofphp/php-cs-fixer": "^3.70.2",
"friendsoftwig/twigcs": "^6.1", "friendsoftwig/twigcs": "^6.5",
"m6web/redis-mock": "^5.6", "m6web/redis-mock": "^5.6",
"php-http/mock-client": "^1.6", "php-http/mock-client": "^1.6.1",
"phpstan/extension-installer": "^1.3.1", "phpstan/extension-installer": "^1.4.3",
"phpstan/phpstan": "^1.10.59", "phpstan/phpstan": "^1.12.20",
"phpstan/phpstan-doctrine": "^1.3.62", "phpstan/phpstan-doctrine": "^1.5.7",
"phpstan/phpstan-phpunit": "^1.3.16", "phpstan/phpstan-phpunit": "^1.4.2",
"phpstan/phpstan-symfony": "^1.3.7", "phpstan/phpstan-symfony": "^1.4.13",
"phpunit/phpunit": "^9.6.17", "phpunit/phpunit": "^9.6.22",
"shipmonk/composer-dependency-analyser": "^1.7", "rector/rector": "^1.2",
"symfony/browser-kit": "^5.4.35", "shipmonk/composer-dependency-analyser": "^1.8.2",
"symfony/css-selector": "^5.4.35", "symfony/css-selector": "^5.4.45",
"symfony/debug-bundle": "^5.4.35", "symfony/debug-bundle": "^5.4.45",
"symfony/maker-bundle": "^1.43", "symfony/maker-bundle": "^1.50",
"symfony/phpunit-bridge": "^7.0.3", "symfony/phpunit-bridge": "^7.2.0",
"symfony/process": "^5.4", "symfony/process": "^5.4.47",
"symfony/var-dumper": "^5.4.35", "symfony/var-dumper": "^5.4.48",
"symfony/web-profiler-bundle": "^5.4.35", "symfony/web-profiler-bundle": "^5.4.48",
"symfony/web-server-bundle": "^4.4.44" "symfony/web-server-bundle": "^4.4.44"
}, },
"replace": {
"symfony/polyfill-php54": "*",
"symfony/polyfill-php55": "*",
"symfony/polyfill-php56": "*",
"symfony/polyfill-php70": "*",
"symfony/polyfill-php71": "*",
"symfony/polyfill-php72": "*",
"symfony/polyfill-php73": "*",
"symfony/polyfill-php74": "*",
"symfony/polyfill-php80": "*",
"symfony/polyfill-php81": "*",
"symfony/polyfill-php82": "*"
},
"suggest": { "suggest": {
"ext-imagick": "To keep GIF animation when downloading image is enabled" "ext-imagick": "To keep GIF animation when downloading image is enabled"
}, },
@ -222,9 +228,6 @@
"phpstan/extension-installer": true "phpstan/extension-installer": true
}, },
"bin-dir": "bin", "bin-dir": "bin",
"platform": {
"php": "7.4.29"
},
"sort-packages": true "sort-packages": true
}, },
"extra": { "extra": {

4120
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,13 @@
FROM php:8.1-fpm AS rootless FROM golang as envsubst
ARG ENVSUBST_VERSION=v1.3.0
# envsubst from gettext can not replace env vars with default values
# this package is not available for ARM32 and we have to build it from source code
# flag -ldflags "-s -w" produces a smaller executable
RUN go install -ldflags "-s -w" -v github.com/a8m/envsubst/cmd/envsubst@${ENVSUBST_VERSION}
FROM php:8.2-fpm AS rootless
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
ARG NODE_VERSION=20 ARG NODE_VERSION=20
@ -12,8 +21,7 @@ RUN apt-get update \
openssl \ openssl \
software-properties-common software-properties-common
RUN curl 'https://deb.nodesource.com/gpgkey/nodesource.gpg.key' | apt-key add - \ RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash -
&& 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 \
@ -51,14 +59,13 @@ RUN docker-php-ext-install -j "$(nproc)" \
tidy \ tidy \
zip zip
RUN pecl install redis; \ RUN pecl install redis-6.1.0 \
pecl install imagick; \ && pecl install imagick-3.7.0 \
pecl install xdebug-3.1.6; \ && pecl install xdebug-3.4.1 \
docker-php-ext-enable \ && docker-php-ext-enable \
redis \ redis \
imagick \ imagick \
xdebug \ xdebug
;
RUN version=$(php -r "echo PHP_MAJOR_VERSION.PHP_MINOR_VERSION;") \ RUN version=$(php -r "echo PHP_MAJOR_VERSION.PHP_MINOR_VERSION;") \
&& architecture=$(uname -m) \ && architecture=$(uname -m) \
@ -77,10 +84,8 @@ RUN mkdir -p /tmp/blackfire \
RUN npm install -g yarn RUN npm install -g yarn
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
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
COPY --from=envsubst /go/bin/envsubst /usr/local/bin/envsubst
COPY entrypoint.sh /entrypoint.sh COPY entrypoint.sh /entrypoint.sh
COPY config/ /opt/wallabag/config/ COPY config/ /opt/wallabag/config/

View file

@ -5,9 +5,9 @@ parameters:
database_name: ${DATABASE_NAME:-symfony} database_name: ${DATABASE_NAME:-symfony}
database_user: ${DATABASE_USER:-root} database_user: ${DATABASE_USER:-root}
database_password: ${DATABASE_PASSWORD:-~} database_password: ${DATABASE_PASSWORD:-~}
database_path: '${DATABASE_PATH:-"%kernel.project_dir%/data/db/wallabag.sqlite"}' database_path: ${DATABASE_PATH:-"%kernel.project_dir%/data/db/wallabag.sqlite"}
database_table_prefix: ${DATABASE_TABLE_PREFIX:-wallabag_} database_table_prefix: ${DATABASE_TABLE_PREFIX:-wallabag_}
database_socket: null database_socket: ${DATABASE_SOCKET:-~}
database_charset: ${DATABASE_CHARSET:-utf8} database_charset: ${DATABASE_CHARSET:-utf8}
domain_name: ${DOMAIN_NAME:-https://www.example.com} domain_name: ${DOMAIN_NAME:-https://www.example.com}
@ -27,22 +27,20 @@ parameters:
fosuser_registration: ${FOSUSER_REGISTRATION:-false} fosuser_registration: ${FOSUSER_REGISTRATION:-false}
fosuser_confirmation: ${FOSUSER_CONFIRMATION:-true} fosuser_confirmation: ${FOSUSER_CONFIRMATION:-true}
fos_oauth_server_access_token_lifetime: 3600 fos_oauth_server_access_token_lifetime: ${FOS_OAUTH_SERVER_ACCESS_TOKEN_LIFETIME:-3600}
fos_oauth_server_refresh_token_lifetime: 1209600 fos_oauth_server_refresh_token_lifetime: ${FOS_OAUTH_SERVER_REFRESH_TOKEN_LIFETIME:-1209600}
from_email: ${FROM_EMAIL:-wallabag@example.com} from_email: ${FROM_EMAIL:-wallabag@example.com}
rss_limit: 50
# RabbitMQ processing # RabbitMQ processing
rabbitmq_host: ${RABBITMQ_HOST:-rabbitmq} rabbitmq_host: ${RABBITMQ_HOST:-rabbitmq}
rabbitmq_port: ${RABBITMQ_PORT:-5672} rabbitmq_port: ${RABBITMQ_PORT:-5672}
rabbitmq_user: ${RABBITMQ_USER:-guest} rabbitmq_user: ${RABBITMQ_USER:-guest}
rabbitmq_password: ${RABBITMQ_PASSWORD:-guest} rabbitmq_password: ${RABBITMQ_PASSWORD:-guest}
rabbitmq_prefetch_count: 10 rabbitmq_prefetch_count: ${RABBITMQ_PREFETCH_COUNT:-10}
# Redis processing # Redis processing
redis_scheme: ${REDIS_SCHEME:-tcp} redis_scheme: ${REDIS_SCHEME:-redis}
redis_host: ${REDIS_HOST:-redis} redis_host: ${REDIS_HOST:-redis}
redis_port: ${REDIS_PORT:-6379} redis_port: ${REDIS_PORT:-6379}
redis_path: ${REDIS_PATH:-~} redis_path: ${REDIS_PATH:-~}

View file

@ -4,9 +4,9 @@ DATABASE_PORT=~
DATABASE_NAME=symfony DATABASE_NAME=symfony
DATABASE_USER=root DATABASE_USER=root
DATABASE_PASSWORD=~ DATABASE_PASSWORD=~
DATABASE_PATH="%kernel.project_dir%/data/db/wallabag.sqlite" DATABASE_PATH='"%kernel.project_dir%/data/db/wallabag.sqlite"'
DOMAIN_NAME=http://localhost:8000 DOMAIN_NAME=http://127.0.0.1:8000
SECRET=ch4n63m31fy0uc4n SECRET=ch4n63m31fy0uc4n
PHP_SESSION_SAVE_PATH=tcp://redis:6379?database=2 PHP_SESSION_SAVE_PATH=redis://redis:6379?database=2
PHP_SESSION_HANDLER=redis PHP_SESSION_HANDLER=redis
TRUSTED_PROXIES=0.0.0.0/0 TRUSTED_PROXIES=0.0.0.0/0

View file

@ -11,7 +11,7 @@ use Wallabag\Entity\User;
class AnnotationFixtures extends Fixture implements DependentFixtureInterface class AnnotationFixtures extends Fixture implements DependentFixtureInterface
{ {
public function load(ObjectManager $manager) public function load(ObjectManager $manager): void
{ {
$annotation1 = new Annotation($this->getReference('admin-user', User::class)); $annotation1 = new Annotation($this->getReference('admin-user', User::class));
$annotation1->setEntry($this->getReference('entry1', Entry::class)); $annotation1->setEntry($this->getReference('entry1', Entry::class));
@ -43,7 +43,7 @@ class AnnotationFixtures extends Fixture implements DependentFixtureInterface
$manager->flush(); $manager->flush();
} }
public function getDependencies() public function getDependencies(): array
{ {
return [ return [
EntryFixtures::class, EntryFixtures::class,

Some files were not shown because too many files have changed in this diff Show more