Merge branch 'master' of https://github.com/wallabag/wallabag
10
.babelrc
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"presets": [
|
|
||||||
[
|
|
||||||
"@babel/preset-env",
|
|
||||||
{
|
|
||||||
"modules": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -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
|
@ -0,0 +1,2 @@
|
||||||
|
# Migrated rules from dependabot.yml
|
||||||
|
composer.* @Kdecherf @j0k3r @yguedidi
|
6
.github/CONTRIBUTING.md
vendored
|
@ -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`.
|
||||||
|
|
17
.github/dependabot.yml
vendored
|
@ -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:
|
||||||
|
|
36
.github/workflows/coding-standards.yml
vendored
|
@ -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"
|
||||||
|
|
51
.github/workflows/continuous-integration.yml
vendored
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
6
.github/workflows/translations.yml
vendored
|
@ -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"
|
||||||
|
|
4
.github/workflows/upload-release-package.yml
vendored
|
@ -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
|
@ -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
|
||||||
|
|
|
@ -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',
|
||||||
],
|
],
|
||||||
|
|
46
CHANGELOG.md
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# wallabag
|
# wallabag
|
||||||
|
|
||||||

|
[](https://github.com/wallabag/wallabag/actions/workflows/continuous-integration.yml?query=branch%3Amaster)
|
||||||
[](https://matrix.to/#/#wallabag:matrix.org)
|
[](https://matrix.to/#/#wallabag:matrix.org)
|
||||||
[](https://liberapay.com/wallabag/donate)
|
[](https://liberapay.com/wallabag/donate)
|
||||||
[](https://hosted.weblate.org/engage/wallabag/?utm_source=widget)
|
[](https://hosted.weblate.org/engage/wallabag/?utm_source=widget)
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,19 +234,11 @@ 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%"
|
lazy: true
|
||||||
user: "%rabbitmq_user%"
|
|
||||||
password: "%rabbitmq_password%"
|
|
||||||
vhost: /
|
|
||||||
lazy: true
|
|
||||||
producers:
|
producers:
|
||||||
import_pocket:
|
import_pocket:
|
||||||
connection: default
|
connection: default
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 }
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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'),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -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',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -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]',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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>';
|
|
|
@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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'); });
|
|
|
@ -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 };
|
|
|
@ -1 +0,0 @@
|
||||||
import './share.scss';
|
|
11
assets/bootstrap.js
vendored
Normal 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
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"controllers": [],
|
||||||
|
"entrypoints": []
|
||||||
|
}
|
13
assets/controllers/add_tag_controller.js
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
57
assets/controllers/annotations_controller.js
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
15
assets/controllers/batch_edit_controller.js
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
16
assets/controllers/clipboard_controller.js
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
16
assets/controllers/config_controller.js
Normal 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`;
|
||||||
|
}
|
||||||
|
}
|
39
assets/controllers/dark_theme_controller.js
Normal 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');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
assets/controllers/entries_navigation_controller.js
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
assets/controllers/fake_radio_controller.js
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
11
assets/controllers/highlight_controller.js
Normal 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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
7
assets/controllers/leftbar_controller.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import { Controller } from '@hotwired/stimulus';
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
toggleAddTagForm() {
|
||||||
|
this.dispatch('toggleAddTagForm');
|
||||||
|
}
|
||||||
|
}
|
16
assets/controllers/materialize/collapsible_controller.js
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
16
assets/controllers/materialize/dropdown_controller.js
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
32
assets/controllers/materialize/fab_controller.js
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
12
assets/controllers/materialize/form_select_controller.js
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
24
assets/controllers/materialize/sidenav_controller.js
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
12
assets/controllers/materialize/tabs_controller.js
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
12
assets/controllers/materialize/toast_controller.js
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
12
assets/controllers/materialize/tooltip_controller.js
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
10
assets/controllers/qrcode_controller.js
Normal 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));
|
||||||
|
}
|
||||||
|
}
|
10
assets/controllers/scroll_indicator_controller.js
Normal 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}%`;
|
||||||
|
}
|
||||||
|
}
|
19
assets/controllers/scroll_storage_controller.js
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
141
assets/controllers/shortcuts_controller.js
Normal 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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
7
assets/controllers/sticky_nav_controller.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import { Controller } from '@hotwired/stimulus';
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
toggle() {
|
||||||
|
this.element.classList.toggle('entry-nav-top--sticky');
|
||||||
|
}
|
||||||
|
}
|
12
assets/controllers/tag_controller.js
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
31
assets/controllers/topbar_controller.js
Normal 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';
|
||||||
|
}
|
||||||
|
}
|
Before Width: | Height: | Size: 891 B After Width: | Height: | Size: 891 B |
Before Width: | Height: | Size: 688 B After Width: | Height: | Size: 688 B |
Before Width: | Height: | Size: 995 B After Width: | Height: | Size: 995 B |
Before Width: | Height: | Size: 1,012 B After Width: | Height: | Size: 1,012 B |
Before Width: | Height: | Size: 718 B After Width: | Height: | Size: 718 B |
19
assets/index.js
Executable 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';
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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,
|
|
||||||
};
|
|
|
@ -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;
|
||||||
}
|
}
|
|
@ -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;
|
|
@ -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%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
@use "material-icons";
|
||||||
@use "variables";
|
@use "variables";
|
||||||
|
|
||||||
/* Style */
|
/* Style */
|
1
assets/share.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
import './scss/share.scss';
|
|
@ -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;
|
||||||
|
|
221
composer.json
|
@ -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": {
|
||||||
|
|
4122
composer.lock
generated
|
@ -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/
|
||||||
|
|
|
@ -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:-~}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|