Compare commits

..

1 Commits

Author SHA1 Message Date
Alexandre Flament
72f5e7cfb8 js_variable_to_python: add tests, handle more JS syntax
The tests from chompjs are copied.
The comment out tests do not pass.
The implementation of js_variable_to_python has been updated:
* in the main looop, try to make the four different cases more clear
* handle decimal number like "-.5", "5." or "- 5"  (without double quote)
* the character ` is seen a string delimiter as intended in JS
* the identifiers follow JS specification ($, _, letters and numbers)
2023-09-16 18:30:57 +00:00
801 changed files with 85152 additions and 176904 deletions

View File

@ -3,8 +3,7 @@
"dockerfile": "Dockerfile" "dockerfile": "Dockerfile"
}, },
"features": { "features": {
"ghcr.io/devcontainers/features/github-cli": {}, "ghcr.io/devcontainers/features/github-cli": {}
"ghcr.io/devcontainers/features/docker-in-docker": {}
}, },
"customizations": { "customizations": {
"vscode": { "vscode": {

View File

@ -16,17 +16,8 @@ max_line_length = 119
[*.html] [*.html]
indent_size = 4 indent_size = 4
[*.css]
indent_size = 2
[*.less]
indent_size = 2
[*.js]
indent_size = 2
[*.json] [*.json]
indent_size = 2 indent_size = 4
insert_final_newline = ignore insert_final_newline = ignore
# Minified JavaScript files shouldn't be changed # Minified JavaScript files shouldn't be changed

View File

@ -1,4 +1,4 @@
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2 version: 2
updates: updates:
- package-ecosystem: "pip" - package-ecosystem: "pip"
@ -8,45 +8,10 @@ updates:
day: "friday" day: "friday"
open-pull-requests-limit: 5 open-pull-requests-limit: 5
target-branch: "master" target-branch: "master"
commit-message:
prefix: "[upd] pypi:"
groups:
minor:
applies-to: version-updates
update-types:
- "minor"
- "patch"
- package-ecosystem: "npm" - package-ecosystem: "npm"
directory: "/client/simple" directory: "/searx/static/themes/simple"
schedule: schedule:
interval: "weekly" interval: "weekly"
day: "friday" day: "friday"
open-pull-requests-limit: 5 open-pull-requests-limit: 5
target-branch: "master" target-branch: "master"
commit-message:
prefix: "[upd] web-client (simple):"
groups:
minor:
applies-to: version-updates
update-types:
- "minor"
- "patch"
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
day: "friday"
target-branch: "master"
commit-message:
prefix: "[upd] docker:"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "friday"
target-branch: "master"
commit-message:
prefix: "[upd] github-actions:"

View File

@ -1,46 +0,0 @@
---
name: Checker
# yamllint disable-line rule:truthy
on:
workflow_dispatch:
schedule:
- cron: "0 4 * * 5"
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
contents: read
env:
PYTHON_VERSION: "3.13"
jobs:
search:
name: Search
runs-on: ubuntu-24.04-arm
steps:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "${{ env.PYTHON_VERSION }}"
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: "false"
- name: Setup cache Python
uses: actions/cache@v4
with:
key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
path: "./local"
- name: Setup venv
run: make V=1 install
- name: Search checker
run: make search.checker

View File

@ -1,34 +0,0 @@
---
name: Cleanup
# yamllint disable-line rule:truthy
on:
workflow_dispatch:
schedule:
- cron: "4 4 * * 0"
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
contents: read
jobs:
container-cache:
name: Container cache
runs-on: ubuntu-24.04
permissions:
# Organization GHCR
packages: write
steps:
- name: Prune
uses: snok/container-retention-policy@v3.0.0
with:
account: "${{ github.repository_owner }}"
token: "${{ secrets.GITHUB_TOKEN }}"
image-names: "cache"
image-tags: "!searxng-*"
cut-off: "1w"
keep-n-most-recent: "100"

View File

@ -1,179 +0,0 @@
---
name: Container
# yamllint disable-line rule:truthy
on:
workflow_dispatch:
workflow_run:
workflows:
- Integration
types:
- completed
branches:
- master
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
contents: read
# Organization GHCR
packages: read
env:
PYTHON_VERSION: "3.13"
jobs:
build:
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
name: Build (${{ matrix.arch }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- arch: amd64
os: ubuntu-24.04
emulation: false
- arch: arm64
os: ubuntu-24.04-arm
emulation: false
- arch: armv7
os: ubuntu-24.04-arm
emulation: true
permissions:
# Organization GHCR
packages: write
outputs:
version_string: ${{ steps.build.outputs.version_string }}
version_tag: ${{ steps.build.outputs.version_tag }}
docker_tag: ${{ steps.build.outputs.docker_tag }}
git_url: ${{ steps.build.outputs.git_url }}
git_branch: ${{ steps.build.outputs.git_branch }}
steps:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "${{ env.PYTHON_VERSION }}"
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: "false"
- name: Setup cache Python
uses: actions/cache@v4
with:
key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
path: "./local/"
- name: Setup cache container mounts
uses: actions/cache@v4
with:
# yamllint disable-line rule:line-length
key: "container-mounts-${{ matrix.arch }}-${{ hashFiles('./container/Dockerfile', './container/legacy/Dockerfile') }}"
restore-keys: "container-mounts-${{ matrix.arch }}-"
path: |
/var/tmp/buildah-cache/
/var/tmp/buildah-cache-*/
- if: ${{ matrix.emulation }}
name: Setup QEMU
uses: docker/setup-qemu-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: "ghcr.io"
username: "${{ github.repository_owner }}"
password: "${{ secrets.GITHUB_TOKEN }}"
- name: Build
id: build
env:
OVERRIDE_ARCH: "${{ matrix.arch }}"
run: make podman.build
test:
name: Test (${{ matrix.arch }})
runs-on: ${{ matrix.os }}
needs: build
strategy:
fail-fast: false
matrix:
include:
- arch: amd64
os: ubuntu-24.04
emulation: false
- arch: arm64
os: ubuntu-24.04-arm
emulation: false
- arch: armv7
os: ubuntu-24.04-arm
emulation: true
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: "false"
- if: ${{ matrix.emulation }}
name: Setup QEMU
uses: docker/setup-qemu-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: "ghcr.io"
username: "${{ github.repository_owner }}"
password: "${{ secrets.GITHUB_TOKEN }}"
- name: Test
env:
OVERRIDE_ARCH: "${{ matrix.arch }}"
GIT_URL: "${{ needs.build.outputs.git_url }}"
run: make container.test
release:
if: github.repository_owner == 'searxng' && github.ref_name == 'master'
name: Release
runs-on: ubuntu-24.04-arm
needs:
- build
- test
permissions:
# Organization GHCR
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: "false"
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: "ghcr.io"
username: "${{ github.repository_owner }}"
password: "${{ secrets.GITHUB_TOKEN }}"
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
registry: "docker.io"
username: "${{ secrets.DOCKERHUB_USERNAME }}"
password: "${{ secrets.DOCKERHUB_TOKEN }}"
- name: Release
env:
GIT_URL: "${{ needs.build.outputs.git_url }}"
DOCKER_TAG: "${{ needs.build.outputs.docker_tag }}"
run: make container.push

View File

@ -1,27 +1,14 @@
--- name: "Update searx.data"
name: Update searx.data
# yamllint disable-line rule:truthy
on: on:
workflow_dispatch:
schedule: schedule:
- cron: "59 23 28 * *" - cron: "59 23 28 * *"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
contents: read
env:
PYTHON_VERSION: "3.13"
jobs: jobs:
data: updateData:
if: github.repository_owner == 'searxng' name: Update data - ${{ matrix.fetch }}
name: ${{ matrix.fetch }} runs-on: ubuntu-20.04
runs-on: ubuntu-24.04-arm if: ${{ github.repository_owner == 'searxng'}}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -33,53 +20,48 @@ jobs:
- update_engine_traits.py - update_engine_traits.py
- update_wikidata_units.py - update_wikidata_units.py
- update_engine_descriptions.py - update_engine_descriptions.py
permissions:
contents: write
pull-requests: write
steps: steps:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "${{ env.PYTHON_VERSION }}"
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
persist-credentials: "false"
- name: Setup cache Python - name: Install Ubuntu packages
uses: actions/cache@v4 run: |
with: sudo ./utils/searxng.sh install packages
key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
path: "./local/"
- name: Setup venv - name: Set up Python
run: make V=1 install uses: actions/setup-python@v2
with:
python-version: '3.9'
architecture: 'x64'
- name: Install Python dependencies
run: |
make V=1 install
- name: Fetch data - name: Fetch data
run: V=1 ./manage pyenv.cmd python "./searxng_extra/update/${{ matrix.fetch }}" env:
FETCH_SCRIPT: ./searxng_extra/update/${{ matrix.fetch }}
run: |
V=1 ./manage pyenv.cmd python "$FETCH_SCRIPT"
- name: Create PR - name: Create Pull Request
id: cpr id: cpr
uses: peter-evans/create-pull-request@v7 uses: peter-evans/create-pull-request@v3
with: with:
author: "searxng-bot <searxng-bot@users.noreply.github.com>" commit-message: Update searx.data - ${{ matrix.fetch }}
committer: "searxng-bot <searxng-bot@users.noreply.github.com>" committer: searxng-bot <noreply@github.com>
title: "[data] update searx.data - ${{ matrix.fetch }}" author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
commit-message: "[data] update searx.data - ${{ matrix.fetch }}" signoff: false
branch: "update_data_${{ matrix.fetch }}" branch: update_data_${{ matrix.fetch }}
delete-branch: "true" delete-branch: true
draft: "false" draft: false
signoff: "false" title: 'Update searx.data - ${{ matrix.fetch }}'
body: | body: |
[data] update searx.data - ${{ matrix.fetch }} Update searx.data - ${{ matrix.fetch }}
labels: | labels: |
data data
- name: Display information - name: Check outputs
run: | run: |
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}" echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}"

View File

@ -1,66 +0,0 @@
---
name: Documentation
# yamllint disable-line rule:truthy
on:
workflow_dispatch:
push:
branches:
- master
pull_request:
branches:
- master
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
contents: read
env:
PYTHON_VERSION: "3.13"
jobs:
release:
name: Release
runs-on: ubuntu-24.04-arm
permissions:
# for JamesIves/github-pages-deploy-action to push
contents: write
steps:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "${{ env.PYTHON_VERSION }}"
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: "false"
fetch-depth: "0"
- name: Setup cache Python
uses: actions/cache@v4
with:
key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
path: "./local/"
- name: Setup venv
run: make V=1 install
- name: Build documentation
run: make V=1 docs.clean docs.html
- if: github.ref_name == 'master'
name: Release
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: "dist/docs"
branch: "gh-pages"
commit-message: "[doc] build from commit ${{ github.sha }}"
# Automatically remove deleted files from the deploy branch
clean: "true"
single-commit: "true"

View File

@ -1,96 +1,214 @@
---
name: Integration name: Integration
# yamllint disable-line rule:truthy
on: on:
push: push:
branches: branches: ["master"]
- master
pull_request: pull_request:
branches: branches: ["master"]
- master
concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}
cancel-in-progress: false
permissions: permissions:
contents: read contents: read
env:
PYTHON_VERSION: "3.13"
jobs: jobs:
test: python:
name: Python ${{ matrix.python-version }} name: Python ${{ matrix.python-version }}
runs-on: ubuntu-24.04 runs-on: ubuntu-20.04
strategy: strategy:
matrix: matrix:
python-version: os: [ubuntu-20.04]
- "3.9" python-version: ["3.8", "3.9", "3.10", "3.11"]
- "3.10"
- "3.11"
- "3.12"
- "3.13"
steps: steps:
- name: Setup Python - name: Checkout
uses: actions/setup-python@v5 uses: actions/checkout@v4
with: - name: Install Ubuntu packages
python-version: "${{ matrix.python-version }}" run: |
sudo ./utils/searxng.sh install packages
sudo apt install firefox
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
uses: actions/cache@v3
with:
path: |
./local
./.nvm
./node_modules
key: python-${{ matrix.os }}-${{ matrix.python-version }}-${{ hashFiles('requirements*.txt', 'setup.py') }}
- name: Install Python dependencies
if: steps.cache-python.outputs.cache-hit != 'true'
run: |
make V=1 install
make V=1 gecko.driver
- name: Run tests
run: make V=1 ci.test
- name: Test coverage
run: make V=1 test.coverage
- name: Store coverage result
uses: actions/upload-artifact@v3
with:
name: coverage-${{ matrix.python-version }}
path: coverage/
retention-days: 60
themes:
name: Themes
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Ubuntu packages
run: sudo ./utils/searxng.sh install buildhost
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
uses: actions/cache@v3
with:
path: |
./local
./.nvm
./node_modules
key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- name: Install node dependencies
run: make V=1 node.env
- name: Build themes
run: make V=1 themes.all
documentation:
name: Documentation
runs-on: ubuntu-20.04
permissions:
contents: write # for JamesIves/github-pages-deploy-action to push changes in repo
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: '0'
persist-credentials: false
- name: Install Ubuntu packages
run: sudo ./utils/searxng.sh install buildhost
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
uses: actions/cache@v3
with:
path: |
./local
./.nvm
./node_modules
key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- name: Build documentation
run: |
make V=1 docs.clean docs.html
- name: Deploy
if: github.ref == 'refs/heads/master'
uses: JamesIves/github-pages-deploy-action@3.7.1
with:
GITHUB_TOKEN: ${{ github.token }}
BRANCH: gh-pages
FOLDER: dist/docs
CLEAN: true # Automatically remove deleted files from the deploy branch
SINGLE_COMMIT: True
COMMIT_MESSAGE: build from commit ${{ github.sha }}
babel:
name: Update translations branch
runs-on: ubuntu-20.04
if: ${{ github.repository_owner == 'searxng' && github.ref == 'refs/heads/master' }}
needs:
- python
- themes
- documentation
permissions:
contents: write # for make V=1 weblate.push.translations
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: '0'
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
uses: actions/cache@v3
with:
path: |
./local
./.nvm
./node_modules
key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- name: weblate & git setup
env:
WEBLATE_CONFIG: ${{ secrets.WEBLATE_CONFIG }}
run: |
mkdir -p ~/.config
echo "${WEBLATE_CONFIG}" > ~/.config/weblate
git config --global user.email "searxng-bot@users.noreply.github.com"
git config --global user.name "searxng-bot"
- name: Update transations
id: update
run: |
git restore utils/brand.env
make V=1 weblate.push.translations
dockers:
name: Docker
if: github.ref == 'refs/heads/master'
needs:
- python
- themes
- documentation
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
runs-on: ubuntu-20.04
steps:
- name: Checkout - name: Checkout
if: env.DOCKERHUB_USERNAME != null
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
persist-credentials: "false" # make sure "make docker.push" can get the git history
fetch-depth: '0'
- name: Setup cache Python - name: Set up Python
uses: actions/cache@v4 uses: actions/setup-python@v4
with: with:
key: "python-${{ matrix.python-version }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}" python-version: '3.9'
restore-keys: "python-${{ matrix.python-version }}-${{ runner.arch }}-" architecture: 'x64'
path: "./local/" - name: Cache Python dependencies
id: cache-python
- name: Setup venv uses: actions/cache@v3
run: make V=1 install
- name: Run tests
run: make V=1 ci.test
theme:
name: Theme
runs-on: ubuntu-24.04-arm
steps:
- name: Setup Python
uses: actions/setup-python@v5
with: with:
python-version: "${{ env.PYTHON_VERSION }}" path: |
./local
- name: Checkout ./.nvm
uses: actions/checkout@v4 ./node_modules
key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- name: Set up QEMU
if: env.DOCKERHUB_USERNAME != null
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
if: env.DOCKERHUB_USERNAME != null
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
if: env.DOCKERHUB_USERNAME != null
uses: docker/login-action@v1
with: with:
persist-credentials: "false" username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Setup Node.js - name: Build and push
uses: actions/setup-node@v4 if: env.DOCKERHUB_USERNAME != null
with: run: make -e GIT_URL=$(git remote get-url origin) docker.buildx
node-version-file: "./.nvmrc"
- name: Setup cache Node.js
uses: actions/cache@v4
with:
key: "nodejs-${{ runner.arch }}-${{ hashFiles('./.nvmrc', './package.json') }}"
path: "./client/simple/node_modules/"
- name: Setup cache Python
uses: actions/cache@v4
with:
key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
path: "./local/"
- name: Setup venv
run: make V=1 install
- name: Build
run: make themes.all

View File

@ -1,138 +0,0 @@
---
name: Translation
# yamllint disable-line rule:truthy
on:
workflow_dispatch:
workflow_run:
workflows:
- Integration
types:
- completed
branches:
- master
schedule:
- cron: "05 07 * * 5"
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
contents: read
env:
PYTHON_VERSION: "3.13"
jobs:
update:
if: github.repository_owner == 'searxng' && github.event.workflow_run.conclusion == 'success'
name: Update
runs-on: ubuntu-24.04-arm
permissions:
# For "make V=1 weblate.push.translations"
contents: write
steps:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "${{ env.PYTHON_VERSION }}"
- name: Checkout
uses: actions/checkout@v4
with:
token: "${{ secrets.WEBLATE_GITHUB_TOKEN }}"
fetch-depth: "0"
- name: Setup cache Python
uses: actions/cache@v4
with:
key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
path: "./local/"
- name: Setup venv
run: make V=1 install
- name: Setup Weblate
run: |
mkdir -p ~/.config
echo "${{ secrets.WEBLATE_CONFIG }}" > ~/.config/weblate
- name: Setup Git
run: |
git config --global user.email "searxng-bot@users.noreply.github.com"
git config --global user.name "searxng-bot"
- name: Update translations
run: make V=1 weblate.push.translations
pr:
if: |
github.repository_owner == 'searxng'
&& (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule')
name: Pull Request
runs-on: ubuntu-24.04-arm
permissions:
# For "make V=1 weblate.translations.commit"
contents: write
# For action "peter-evans/create-pull-request"
pull-requests: write
steps:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "${{ env.PYTHON_VERSION }}"
- name: Checkout
uses: actions/checkout@v4
with:
token: "${{ secrets.WEBLATE_GITHUB_TOKEN }}"
fetch-depth: "0"
- name: Setup cache Python
uses: actions/cache@v4
with:
key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
path: "./local/"
- name: Setup venv
run: make V=1 install
- name: Setup Weblate
run: |
mkdir -p ~/.config
echo "${{ secrets.WEBLATE_CONFIG }}" > ~/.config/weblate
- name: Setup Git
run: |
git config --global user.email "searxng-bot@users.noreply.github.com"
git config --global user.name "searxng-bot"
- name: Merge and push translation updates
run: make V=1 weblate.translations.commit
- name: Create PR
id: cpr
uses: peter-evans/create-pull-request@v7
with:
author: "searxng-bot <searxng-bot@users.noreply.github.com>"
committer: "searxng-bot <searxng-bot@users.noreply.github.com>"
title: "[l10n] update translations from Weblate"
commit-message: "[l10n] update translations from Weblate"
branch: "translations_update"
delete-branch: "true"
draft: "false"
signoff: "false"
body: |
[l10n] update translations from Weblate
labels: |
translation
- name: Display information
run: |
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}"

View File

@ -1,43 +1,28 @@
--- name: "Security checks"
name: Security
# yamllint disable-line rule:truthy
on: on:
workflow_dispatch:
schedule: schedule:
- cron: "42 05 * * *" - cron: "42 05 * * *"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
contents: read
jobs: jobs:
container: dockers:
name: Container name: Trivy ${{ matrix.image }}
runs-on: ubuntu-24.04-arm runs-on: ubuntu-20.04
permissions:
security-events: write
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
persist-credentials: "false"
- name: Run Trivy scanner - name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@0.30.0 uses: aquasecurity/trivy-action@master
with: with:
image-ref: "docker.io/searxng/searxng:latest" image-ref: 'searxng/searxng:latest'
vuln-type: "os,library" ignore-unfixed: false
severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL" vuln-type: 'os,library'
ignore-unfixed: "false" severity: 'UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL'
format: "sarif" format: 'sarif'
output: "./trivy-results.sarif" output: 'trivy-results.sarif'
- name: Upload SARIFs - name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3 uses: github/codeql-action/upload-sarif@v2
with: with:
sarif_file: "./trivy-results.sarif" sarif_file: 'trivy-results.sarif'

View File

@ -0,0 +1,59 @@
name: "Update translations"
on:
schedule:
- cron: "05 07 * * 5"
workflow_dispatch:
jobs:
babel:
name: "create PR for additions from weblate"
runs-on: ubuntu-20.04
if: ${{ github.repository_owner == 'searxng' && github.ref == 'refs/heads/master' }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: '0'
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
uses: actions/cache@v3
with:
path: |
./local
./.nvm
./node_modules
key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- name: weblate & git setup
env:
WEBLATE_CONFIG: ${{ secrets.WEBLATE_CONFIG }}
run: |
mkdir -p ~/.config
echo "${WEBLATE_CONFIG}" > ~/.config/weblate
git config --global user.email "searxng-bot@users.noreply.github.com"
git config --global user.name "searxng-bot"
- name: Merge and push transation updates
run: |
make V=1 weblate.translations.commit
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@v3
with:
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
commit-message: Update translations
committer: searxng-bot <searxng-bot@users.noreply.github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
signoff: false
branch: translations_update
delete-branch: true
draft: false
title: 'Update translations'
body: |
Update translations
labels: |
translation

3
.gitignore vendored
View File

@ -23,6 +23,3 @@ gh-pages/
.idea/ .idea/
searx/version_frozen.py searx/version_frozen.py
.dir-locals.el
.python-version

2
.nvmrc
View File

@ -1 +1 @@
v23.5 v16.15.1

View File

@ -1,4 +1,4 @@
# -*- coding: utf-8; mode: conf-unix -*- # -*- coding: utf-8; mode: conf -*-
# lint Python modules using external checkers. # lint Python modules using external checkers.
# #
# This is the main checker controlling the other ones and the reports # This is the main checker controlling the other ones and the reports
@ -27,7 +27,7 @@ ignore-patterns=
#init-hook= #init-hook=
# Use multiple processes to speed up Pylint. # Use multiple processes to speed up Pylint.
jobs=0 jobs=1
# List of plugins (as comma separated values of python modules names) to load, # List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers. # usually to register additional checkers.
@ -338,7 +338,6 @@ valid-metaclass-classmethod-first-arg=mcs
# Maximum number of arguments for function / method # Maximum number of arguments for function / method
max-args=8 max-args=8
max-positional-arguments=14
# Maximum number of attributes for a class (see R0902). # Maximum number of attributes for a class (see R0902).
max-attributes=20 max-attributes=20

View File

@ -1,4 +0,0 @@
nodejs 23.5.0
python 3.13.1
shellcheck 0.10.0
sqlite 3.47.2

View File

@ -169,11 +169,3 @@ features or generally made searx better:
- @llmII - @llmII
- @blob42 `<https://blob42.xyz>`_ - @blob42 `<https://blob42.xyz>`_
- Paolo Basso `<https://github.com/paolobasso99>` - Paolo Basso `<https://github.com/paolobasso99>`
- Bernie Huang `<https://github.com/BernieHuang2008>`
- Austin Olacsi `<https://github.com/Austin-Olacsi>`
- @micsthepick
- Daniel Kukula `<https://github.com/dkuku>`
- Patrick Evans `https://github.com/holysoles`
- Daniel Mowitz `<https://daniel.mowitz.rocks>`
- `Bearz314 <https://github.com/bearz314>`_
- Tommaso Colella `<https://github.com/gioleppe>`

View File

@ -2,7 +2,7 @@
## Resources in the documentation ## Resources in the documentation
* [Development quickstart](https://docs.searxng.org/dev/quickstart.html) * [Development quickstart](https://docs.searxng.org/dev/contribution_guide.html)
* [Contribution guide](https://docs.searxng.org/dev/contribution_guide.html) * [Contribution guide](https://docs.searxng.org/dev/contribution_guide.html)
## Submitting PRs ## Submitting PRs

88
Dockerfile Normal file
View File

@ -0,0 +1,88 @@
FROM alpine:3.18
ENTRYPOINT ["/sbin/tini","--","/usr/local/searxng/dockerfiles/docker-entrypoint.sh"]
EXPOSE 8080
VOLUME /etc/searxng
ARG SEARXNG_GID=977
ARG SEARXNG_UID=977
RUN addgroup -g ${SEARXNG_GID} searxng && \
adduser -u ${SEARXNG_UID} -D -h /usr/local/searxng -s /bin/sh -G searxng searxng
ENV INSTANCE_NAME=searxng \
AUTOCOMPLETE= \
BASE_URL= \
MORTY_KEY= \
MORTY_URL= \
SEARXNG_SETTINGS_PATH=/etc/searxng/settings.yml \
UWSGI_SETTINGS_PATH=/etc/searxng/uwsgi.ini
WORKDIR /usr/local/searxng
COPY requirements.txt ./requirements.txt
RUN apk add --no-cache -t build-dependencies \
build-base \
py3-setuptools \
python3-dev \
libffi-dev \
libxslt-dev \
libxml2-dev \
openssl-dev \
tar \
git \
&& apk add --no-cache \
ca-certificates \
su-exec \
python3 \
py3-pip \
libxml2 \
libxslt \
openssl \
tini \
uwsgi \
uwsgi-python3 \
brotli \
&& pip3 install --no-cache -r requirements.txt \
&& apk del build-dependencies \
&& rm -rf /root/.cache
COPY --chown=searxng:searxng dockerfiles ./dockerfiles
COPY --chown=searxng:searxng searx ./searx
ARG TIMESTAMP_SETTINGS=0
ARG TIMESTAMP_UWSGI=0
ARG VERSION_GITCOMMIT=unknown
RUN su searxng -c "/usr/bin/python3 -m compileall -q searx" \
&& touch -c --date=@${TIMESTAMP_SETTINGS} searx/settings.yml \
&& touch -c --date=@${TIMESTAMP_UWSGI} dockerfiles/uwsgi.ini \
&& find /usr/local/searxng/searx/static -a \( -name '*.html' -o -name '*.css' -o -name '*.js' \
-o -name '*.svg' -o -name '*.ttf' -o -name '*.eot' \) \
-type f -exec gzip -9 -k {} \+ -exec brotli --best {} \+
# Keep these arguments at the end to prevent redundant layer rebuilds
ARG LABEL_DATE=
ARG GIT_URL=unknown
ARG SEARXNG_GIT_VERSION=unknown
ARG SEARXNG_DOCKER_TAG=unknown
ARG LABEL_VCS_REF=
ARG LABEL_VCS_URL=
LABEL maintainer="searxng <${GIT_URL}>" \
description="A privacy-respecting, hackable metasearch engine." \
version="${SEARXNG_GIT_VERSION}" \
org.label-schema.schema-version="1.0" \
org.label-schema.name="searxng" \
org.label-schema.version="${SEARXNG_GIT_VERSION}" \
org.label-schema.url="${LABEL_VCS_URL}" \
org.label-schema.vcs-ref=${LABEL_VCS_REF} \
org.label-schema.vcs-url=${LABEL_VCS_URL} \
org.label-schema.build-date="${LABEL_DATE}" \
org.label-schema.usage="https://github.com/searxng/searxng-docker" \
org.opencontainers.image.title="searxng" \
org.opencontainers.image.version="${SEARXNG_DOCKER_TAG}" \
org.opencontainers.image.url="${LABEL_VCS_URL}" \
org.opencontainers.image.revision=${LABEL_VCS_REF} \
org.opencontainers.image.source=${LABEL_VCS_URL} \
org.opencontainers.image.created="${LABEL_DATE}" \
org.opencontainers.image.documentation="https://github.com/searxng/searxng-docker"

View File

@ -44,19 +44,19 @@ lxc.clean:
PHONY += search.checker search.checker.% PHONY += search.checker search.checker.%
search.checker: install search.checker: install
$(Q)./manage pyenv.cmd searxng-checker -v $(Q)./manage pyenv.cmd searx-checker -v
search.checker.%: install search.checker.%: install
$(Q)./manage pyenv.cmd searxng-checker -v "$(subst _, ,$(patsubst search.checker.%,%,$@))" $(Q)./manage pyenv.cmd searx-checker -v "$(subst _, ,$(patsubst search.checker.%,%,$@))"
PHONY += test ci.test test.shell PHONY += test ci.test test.shell
ci.test: test.yamllint test.black test.types.ci test.pylint test.unit test.robot test.rst test.shell test.pybabel ci.test: test.yamllint test.black test.pyright test.pylint test.unit test.robot test.rst test.pybabel
test: test.yamllint test.black test.types.dev test.pylint test.unit test.robot test.rst test.shell test: test.yamllint test.black test.pyright test.pylint test.unit test.robot test.rst test.shell
test.shell: test.shell:
$(Q)shellcheck -x -s dash \ $(Q)shellcheck -x -s dash \
container/docker-entrypoint.sh dockerfiles/docker-entrypoint.sh
$(Q)shellcheck -x -s bash \ $(Q)shellcheck -x -s bash \
utils/brand.sh \ utils/brand.env \
$(MTOOLS) \ $(MTOOLS) \
utils/lib.sh \ utils/lib.sh \
utils/lib_sxng*.sh \ utils/lib_sxng*.sh \
@ -65,25 +65,28 @@ test.shell:
utils/lib_redis.sh \ utils/lib_redis.sh \
utils/searxng.sh \ utils/searxng.sh \
utils/lxc.sh \ utils/lxc.sh \
utils/lxc-searxng.env utils/lxc-searxng.env \
utils/searx.sh \
utils/filtron.sh \
utils/morty.sh
$(Q)$(MTOOLS) build_msg TEST "$@ OK" $(Q)$(MTOOLS) build_msg TEST "$@ OK"
# wrap ./manage script # wrap ./manage script
MANAGE += buildenv
MANAGE += weblate.translations.commit weblate.push.translations MANAGE += weblate.translations.commit weblate.push.translations
MANAGE += data.all data.traits data.useragents data.locales data.currencies MANAGE += data.all data.traits data.useragents
MANAGE += docs.html docs.live docs.gh-pages docs.prebuild docs.clean MANAGE += docs.html docs.live docs.gh-pages docs.prebuild docs.clean
MANAGE += podman.build MANAGE += docker.build docker.push docker.buildx
MANAGE += docker.build docker.buildx
MANAGE += container.build container.test container.push
MANAGE += gecko.driver MANAGE += gecko.driver
MANAGE += node.env node.env.dev node.clean MANAGE += node.env node.env.dev node.clean
MANAGE += py.build py.clean MANAGE += py.build py.clean
MANAGE += pyenv pyenv.install pyenv.uninstall MANAGE += pyenv pyenv.install pyenv.uninstall
MANAGE += pypi.upload pypi.upload.test
MANAGE += format.python MANAGE += format.python
MANAGE += test.yamllint test.pylint test.black test.pybabel test.unit test.coverage test.robot test.rst test.clean test.themes test.types.dev test.types.ci MANAGE += test.yamllint test.pylint test.pyright test.black test.pybabel test.unit test.coverage test.robot test.rst test.clean
MANAGE += themes.all themes.fix themes.test MANAGE += themes.all themes.simple themes.simple.test pygments.less
MANAGE += static.build.commit static.build.drop static.build.restore MANAGE += static.build.commit static.build.drop static.build.restore
MANAGE += nvm.install nvm.clean nvm.status nvm.nodejs MANAGE += nvm.install nvm.clean nvm.status nvm.nodejs
@ -94,8 +97,8 @@ $(MANAGE):
# short hands of selected targets # short hands of selected targets
PHONY += docs container themes PHONY += docs docker themes
docs: docs.html docs: docs.html
container: container.build docker: docker.build
themes: themes.all themes: themes.all

View File

@ -2,7 +2,7 @@
---- ----
.. figure:: https://raw.githubusercontent.com/searxng/searxng/master/client/simple/src/brand/searxng.svg .. figure:: https://raw.githubusercontent.com/searxng/searxng/master/src/brand/searxng.svg
:target: https://docs.searxng.org/ :target: https://docs.searxng.org/
:alt: SearXNG :alt: SearXNG
:width: 100% :width: 100%
@ -34,7 +34,7 @@ A user_, admin_ and developer_ handbook is available on the homepage_.
.. _homepage: https://docs.searxng.org/ .. _homepage: https://docs.searxng.org/
.. _metasearch engine: https://en.wikipedia.org/wiki/Metasearch_engine .. _metasearch engine: https://en.wikipedia.org/wiki/Metasearch_engine
.. |SearXNG logo| image:: https://raw.githubusercontent.com/searxng/searxng/master/client/simple/src/brand/searxng-wordmark.svg .. |SearXNG logo| image:: https://raw.githubusercontent.com/searxng/searxng/master/src/brand/searxng-wordmark.svg
:target: https://docs.searxng.org/ :target: https://docs.searxng.org/
:width: 5% :width: 5%
@ -66,7 +66,7 @@ A user_, admin_ and developer_ handbook is available on the homepage_.
Contact Contact
======= =======
Ask questions or chat with the SearXNG community (this not a chatbot) on Ask questions or just chat about SearXNG on
IRC IRC
`#searxng on libera.chat <https://web.libera.chat/?channel=#searxng>`_ `#searxng on libera.chat <https://web.libera.chat/?channel=#searxng>`_
@ -121,9 +121,9 @@ You can contribute from your browser using `GitHub Codespaces`_:
- Click on the ``Codespaces`` tab instead of ``Local`` - Click on the ``Codespaces`` tab instead of ``Local``
- Click on ``Create codespace on master`` - Click on ``Create codespace on master``
- VSCode is going to start in the browser - VSCode is going to start in the browser
- Wait for ``git pull && make install`` to appear and then disappear - Wait for ``git pull && make install`` to appears and then to disapear
- You have `120 hours per month`_ (see also your `list of existing Codespaces`_) - You have `120 hours per month`_ (see also your `list of existing Codespaces`_)
- You can start SearXNG using ``make run`` in the terminal or by pressing ``Ctrl+Shift+B`` - You can start SearXNG using ``make run`` in the terminal or by pressing ``Ctrl+Shift+B``.
.. _GitHub Codespaces: https://docs.github.com/en/codespaces/overview .. _GitHub Codespaces: https://docs.github.com/en/codespaces/overview
.. _120 hours per month: https://github.com/settings/billing .. _120 hours per month: https://github.com/settings/billing

View File

@ -1,3 +0,0 @@
dist
node_modules
.stylelintcache

View File

@ -1,17 +0,0 @@
{
"formatter": "unix",
"plugins": [ "stylelint-prettier" ],
"extends": [ "stylelint-config-standard-less" ],
"rules": {
"prettier/prettier": true,
"declaration-empty-line-before": null,
"no-invalid-position-at-import-rule": null,
"property-no-vendor-prefix": null,
"selector-no-vendor-prefix": null,
"selector-attribute-quotes": null,
"shorthand-property-no-redundant-values": null,
"at-rule-no-vendor-prefix": null,
"selector-id-pattern": null,
"selector-class-pattern": null
}
}

View File

@ -1,24 +0,0 @@
=====================
MEMO vite development
=====================
Local install::
# in folder ./client/simple/
$ npm install
Start development server::
$ ./manage vite.simple.dev
# in folder ./client/simple/
$ npm exec -- vite
Fix source code::
# in folder ./client/simple/
$ npm run fix
Fix & Build::
$ ./manage vite.simple.build

View File

@ -1,34 +0,0 @@
import globals from "globals";
import pluginJs from "@eslint/js";
/** @type {import('eslint').Linter.Config[]} */
export default [
pluginJs.configs.recommended,
// global "ignores"
// https://eslint.org/docs/latest/use/configure/configuration-files#globally-ignoring-files-with-ignores
{
ignores: ["node_modules/", "dist/"]
},
{
files: [
"**/*.js",
],
linterOptions: {
reportUnusedDisableDirectives: "error",
// noInlineConfig: true
},
languageOptions: {
sourceType: "module",
globals: {
...globals.browser,
}
},
rules: {
indent: ["error", 2],
},
},
];

File diff suppressed because it is too large Load Diff

View File

@ -1,41 +0,0 @@
{
"name": "simple",
"version": "1.0.0",
"type": "module",
"scripts": {
"clean": "rm -Rf node_modules",
"build": "node theme_icons.js && vite build",
"fix": "eslint --fix && stylelint --fix strict 'src/**/*.{css,scss,sass,less,styl,vue,svelte}'",
"icons.html": "node theme_icons.js"
},
"devDependencies": {
"@eslint/js": "^9.26.0",
"copy-webpack-plugin": "^13.0.0",
"css-loader": "^7.1.2",
"edge.js": "^6.2.1",
"eslint": "^9.26.0",
"filemanager-webpack-plugin": "^8.0.0",
"globals": "^16.1.0",
"ionicons": "^8.0.8",
"leaflet": "^1.9.4",
"less": "^4.3.0",
"less-loader": "^12.3.0",
"normalize.css": "^8.0.1",
"sharp": "^0.34.1",
"style-loader": "^4.0.0",
"stylelint": "^16.19.1",
"stylelint-config-standard": "^38.0.0",
"stylelint-config-standard-less": "^3.0.1",
"stylelint-prettier": "^5.0.3",
"svgo": "^3.3.2",
"swiped-events": "^1.2.0",
"vite": "^6.3.5",
"vite-plugin-static-copy": "^2.3.1",
"vite-plugin-stylelint": "^6.0.0",
"webpack": "^5.99.8",
"webpack-cli": "^6.0.1"
},
"dependencies": {
"autocomplete-js": "^2.7.1"
}
}

View File

@ -1,184 +0,0 @@
/* SPDX-License-Identifier: AGPL-3.0-or-later */
import "../../../node_modules/swiped-events/src/swiped-events.js";
(function (w, d, searxng) {
'use strict';
if (searxng.endpoint !== 'results') {
return;
}
searxng.ready(function () {
d.querySelectorAll('#urls img').forEach(
img =>
img.addEventListener(
'error', () => {
// console.log("ERROR can't load: " + img.src);
img.src = window.searxng.settings.theme_static_path + "/img/img_load_error.svg";
},
{once: true}
));
if (d.querySelector('#search_url button#copy_url')) {
d.querySelector('#search_url button#copy_url').style.display = "block";
}
searxng.on('.btn-collapse', 'click', function () {
var btnLabelCollapsed = this.getAttribute('data-btn-text-collapsed');
var btnLabelNotCollapsed = this.getAttribute('data-btn-text-not-collapsed');
var target = this.getAttribute('data-target');
var targetElement = d.querySelector(target);
var html = this.innerHTML;
if (this.classList.contains('collapsed')) {
html = html.replace(btnLabelCollapsed, btnLabelNotCollapsed);
} else {
html = html.replace(btnLabelNotCollapsed, btnLabelCollapsed);
}
this.innerHTML = html;
this.classList.toggle('collapsed');
targetElement.classList.toggle('invisible');
});
searxng.on('.media-loader', 'click', function () {
var target = this.getAttribute('data-target');
var iframe_load = d.querySelector(target + ' > iframe');
var srctest = iframe_load.getAttribute('src');
if (srctest === null || srctest === undefined || srctest === false) {
iframe_load.setAttribute('src', iframe_load.getAttribute('data-src'));
}
});
searxng.on('#copy_url', 'click', function () {
var target = this.parentElement.querySelector('pre');
navigator.clipboard.writeText(target.innerText);
this.innerText = this.dataset.copiedText;
});
// searxng.selectImage (gallery)
// -----------------------------
// setTimeout() ID, needed to cancel *last* loadImage
let imgTimeoutID;
// progress spinner, while an image is loading
const imgLoaderSpinner = d.createElement('div');
imgLoaderSpinner.classList.add('loader');
// singleton image object, which is used for all loading processes of a
// detailed image
const imgLoader = new Image();
const loadImage = (imgSrc, onSuccess) => {
// if defered image load exists, stop defered task.
if (imgTimeoutID) clearTimeout(imgTimeoutID);
// defer load of the detail image for 1 sec
imgTimeoutID = setTimeout(() => {
imgLoader.src = imgSrc;
}, 1000);
// set handlers in the on-properties
imgLoader.onload = () => {
onSuccess();
imgLoaderSpinner.remove();
};
imgLoader.onerror = () => {
imgLoaderSpinner.remove();
};
};
searxng.selectImage = (resultElement) => {
// add a class that can be evaluated in the CSS and indicates that the
// detail view is open
d.getElementById('results').classList.add('image-detail-open');
// add a hash to the browser history so that pressing back doesn't return
// to the previous page this allows us to dismiss the image details on
// pressing the back button on mobile devices
window.location.hash = '#image-viewer';
searxng.scrollPageToSelected();
// if there is none element given by the caller, stop here
if (!resultElement) return;
// find <img> object in the element, if there is none, stop here.
const img = resultElement.querySelector('.result-images-source img');
if (!img) return;
// <img src="" data-src="http://example.org/image.jpg">
const src = img.getAttribute('data-src');
// already loaded high-res image or no high-res image available
if (!src) return;
// use the image thumbnail until the image is fully loaded
const thumbnail = resultElement.querySelector('.image_thumbnail');
img.src = thumbnail.src;
// show a progress spinner
const detailElement = resultElement.querySelector('.detail');
detailElement.appendChild(imgLoaderSpinner);
// load full size image in background
loadImage(src, () => {
// after the singelton loadImage has loaded the detail image into the
// cache, it can be used in the origin <img> as src property.
img.src = src;
img.removeAttribute('data-src');
});
};
searxng.closeDetail = function () {
d.getElementById('results').classList.remove('image-detail-open');
// remove #image-viewer hash from url by navigating back
if (window.location.hash == '#image-viewer') window.history.back();
searxng.scrollPageToSelected();
};
searxng.on('.result-detail-close', 'click', e => {
e.preventDefault();
searxng.closeDetail();
});
searxng.on('.result-detail-previous', 'click', e => {
e.preventDefault();
searxng.selectPrevious(false);
});
searxng.on('.result-detail-next', 'click', e => {
e.preventDefault();
searxng.selectNext(false);
});
// listen for the back button to be pressed and dismiss the image details when called
window.addEventListener('hashchange', () => {
if (window.location.hash != '#image-viewer') searxng.closeDetail();
});
d.querySelectorAll('.swipe-horizontal').forEach(
obj => {
obj.addEventListener('swiped-left', function () {
searxng.selectNext(false);
});
obj.addEventListener('swiped-right', function () {
searxng.selectPrevious(false);
});
}
);
w.addEventListener('scroll', function () {
var e = d.getElementById('backToTop'),
scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
results = d.getElementById('results');
if (e !== null) {
if (scrollTop >= 100) {
results.classList.add('scrolling');
} else {
results.classList.remove('scrolling');
}
}
}, true);
});
})(window, document, window.searxng);

View File

@ -1 +0,0 @@
import "./head/00_init.js";

View File

@ -1,7 +0,0 @@
import "./main/00_toolkit.js";
import "./main/infinite_scroll.js";
import "./main/keyboard.js";
import "./main/mapresult.js";
import "./main/preferences.js";
import "./main/results.js";
import "./main/search.js";

View File

@ -1,35 +0,0 @@
/*
Layout of the KeyValue result class
*/
#main_results .result-keyvalue {
caption {
padding: 0.8rem 0.5rem;
font-style: italic;
caption-side: bottom;
background-color: var(--color-result-keyvalue-table);
}
.col-key {
width: 25%;
}
table {
word-break: break-word;
table-layout: fixed;
width: 100%;
background-color: var(--color-result-keyvalue-table);
}
tr.odd {
background-color: var(--color-result-keyvalue-odd);
}
tr.even {
background-color: var(--color-result-keyvalue-even);
}
th,
td {
padding: 0.3rem 0.5rem;
}
}

View File

@ -1,45 +0,0 @@
@import (inline) "../../node_modules/normalize.css/normalize.css";
@import "definitions.less";
.text-size-adjust (@property: 100%) {
-webkit-text-size-adjust: @property;
-ms-text-size-adjust: @property;
-moz-text-size-adjust: @property;
text-size-adjust: @property;
}
// Reset padding and margin
html,
body,
main {
padding: 0;
margin: 0;
}
html {
font-family: sans-serif;
font-size: 0.9em;
.text-size-adjust;
color: var(--color-base-font);
background-color: var(--color-base-background);
scroll-behavior: smooth;
}
body {
margin-inline: 1rem;
}
a {
text-decoration: none;
color: var(--color-url-font);
&:visited {
color: var(--color-url-visited-font);
.highlight {
color: var(--color-url-visited-font);
}
}
}

View File

@ -1,29 +0,0 @@
.loader,
.loader::after {
border-radius: 50%;
width: 10em;
height: 10em;
}
.loader {
margin: 60px auto;
font-size: 10px;
position: relative;
text-indent: -9999em;
border-top: 1.1em solid var(--color-loading-indicator);
border-right: 1.1em solid var(--color-loading-indicator);
border-bottom: 1.1em solid var(--color-loading-indicator);
border-left: 1.1em solid var(--color-loading-indicator-gap);
transform: translateZ(0);
animation: load8 1.1s infinite linear;
}
@keyframes load8 {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}

View File

@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<path fill="#58f" d="M11 20.85a.92.92 0 0 1-1.1.93A10 10 0 0 1 2.06 13c-.06-.55.4-1 .95-1h3a1 1 0 0 1 1 1 3 3 0 0 0 3 3 1 1 0 0 1 1 1v3.85Zm6-1.92c0 .77.83 1.23 1.42.74a10 10 0 0 0 2.03-2.32c.39-.61-.09-1.35-.81-1.35H18a1 1 0 0 0-1 1v1.93ZM12 2a10 10 0 0 1 6.65 2.53c.61.55.17 1.47-.65 1.47h-.15A2.85 2.85 0 0 0 15 8.85c0 .33-.18.62-.47.77l-.08.04a1 1 0 0 1-.9 0l-.08-.04a.85.85 0 0 1-.47-.77A2.85 2.85 0 0 0 10.15 6H10a1 1 0 0 1-1-1V3.2c0-.44.28-.84.7-.94C10.45 2.1 11.22 2 12 2Z"/>
<path fill="#58f" d="M3.42 10c-.63 0-1.1-.58-.9-1.18.6-1.8 1.7-3.36 3.12-4.53C6.2 3.82 7 4.26 7 5a3 3 0 0 0 3 3h.15c.47 0 .85.38.85.85 0 1.09.61 2.07 1.58 2.56l.08.04a3 3 0 0 0 2.68 0l.08-.04A2.85 2.85 0 0 0 17 8.85c0-.47.38-.85.85-.85h2.66c.4 0 .77.23.9.6a9.98 9.98 0 0 1 .52 4.6.94.94 0 0 1-.95.8H18a3 3 0 0 0-3 3v3.8c0 .44-.28.84-.7.94l-.2.04a.92.92 0 0 1-1.1-.93V17a3 3 0 0 0-3-3 1 1 0 0 1-1-1 3 3 0 0 0-3-3H3.42Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 989 B

View File

@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path d="M248 64C146.39 64 64 146.39 64 248s82.39 184 184 184 184-82.39 184-184S349.61 64 248 64z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/>
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M220 220h32v116"/>
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="32" d="M208 340h88"/>
<path d="M248 130a26 26 0 1026 26 26 26 0 00-26-26z" fill="currentColor" stroke="currentColor" stroke-miterlimit="10" stroke-width="1"/>
</svg>

Before

Width:  |  Height:  |  Size: 648 B

View File

@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path d="M368 415.86V72a24.07 24.07 0 00-24-24H72a24.07 24.07 0 00-24 24v352a40.12 40.12 0 0040 40h328" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/>
<path d="M416 464h0a48 48 0 01-48-48V128h72a24 24 0 0124 24v264a48 48 0 01-48 48z" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/>
<path d="M240 128h64M240 192h64M112 256h192M112 320h192M112 384h192" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/>
<path d="M176 208h-64a16 16 0 01-16-16v-64a16 16 0 0116-16h64a16 16 0 0116 16v64a16 16 0 01-16 16z" fill="currentColor" stroke="currentColor" stroke-linejoin="round" stroke-width="1" />
</svg>

Before

Width:  |  Height:  |  Size: 787 B

View File

@ -1,2 +0,0 @@
leaflet.css -diff
leaflet.js -diff

View File

@ -1,84 +0,0 @@
/**
* Generate icons.html for the jinja templates of the simple theme.
*/
import { argv } from "node:process";
import { dirname, resolve } from "node:path";
import { jinja_svg_sets } from "./tools/jinja_svg_catalog.js";
const HERE = dirname(argv[1]) + "/";
const dest = resolve(HERE, "../../searx/templates/simple/icons.html");
/** @type import("./tools/jinja_svg_catalog.js").JinjaMacro[] */
const searxng_jinja_macros = [
{ name: "icon", class: "sxng-icon-set" },
{ name: "icon_small", class: "sxng-icon-set-small" },
{ name: "icon_big", class: "sxng-icon-set-big" },
];
const sxng_icon_opts ={
multipass: true,
plugins: [
{ name: "removeTitle" },
{ name: "removeXMLNS" },
{ name: "addAttributesToSVGElement",
params: {
attributes: [
{
"aria-hidden": "true",
}]}}]
};
/** @type import("./tools/jinja_svg_catalog.js").IconSet */
const simple_icons = [
{
base: resolve(HERE, "node_modules/ionicons/dist/svg"),
set: {
"alert": "alert-outline.svg",
"appstore": "apps-outline.svg",
"book": "book-outline.svg",
"close": "close-outline.svg",
"download": "download-outline.svg",
"ellipsis-vertical": "ellipsis-vertical-outline.svg",
"file-tray-full": "file-tray-full-outline.svg",
"film": "film-outline.svg",
"globe": "globe-outline.svg",
"heart": "heart-outline.svg",
"image": "image-outline.svg",
"layers": "layers-outline.svg",
"leecher": "arrow-down.svg",
"location": "location-outline.svg",
"magnet": "magnet-outline.svg",
"musical-notes": "musical-notes-outline.svg",
"navigate-down": "chevron-down-outline.svg",
"navigate-left": "chevron-back-outline.svg",
"navigate-right": "chevron-forward-outline.svg",
"navigate-up": "chevron-up-outline.svg",
"people": "people-outline.svg",
"play": "play-outline.svg",
"radio": "radio-outline.svg",
"save": "save-outline.svg",
"school": "school-outline.svg",
"search": "search-outline.svg",
"seeder": "swap-vertical.svg",
"settings": "settings-outline.svg",
"tv": "tv-outline.svg",
},
svgo_opts: sxng_icon_opts,
},
// some of the ionicons are not suitable for a dark theme, we fixed the svg
// manually in src/svg/ionicons
// - https://github.com/searxng/searxng/pull/4284#issuecomment-2680550342
{
base: resolve(HERE, "src/svg/ionicons"),
set: {
"information-circle": "information-circle-outline.svg",
"newspaper": "newspaper-outline.svg",
},
svgo_opts: sxng_icon_opts,
}
];
jinja_svg_sets(dest, searxng_jinja_macros, simple_icons);

View File

@ -1,78 +0,0 @@
import fs from "fs";
import path from "path";
import sharp from "sharp";
import { optimize as svgo } from "svgo";
/**
* @typedef {object} Src2Dest - Mapping of src to dest
* @property {string} src - Name of the source file.
* @property {string} dest - Name of the destination file.
*/
/**
* Convert a list of SVG files to PNG.
*
* @param {Src2Dest[]} items - Array of SVG files (src: SVG, dest:PNG) to convert.
*/
async function svg2png (items) {
items.forEach(
async (item) => {
try {
fs.mkdir(path.dirname(item.dest), { recursive: true }, (err) => {
if (err)
throw err;
});
const info = await sharp(item.src).png({
force: true,
compressionLevel: 9,
palette: true,
}).toFile(item.dest);
console.log(
`[svg2png] created ${item.dest} -- bytes: ${info.size}, w:${info.width}px, h:${info.height}px`
);
} catch (err) {
console.error(`ERROR: ${item.dest} -- ${err}`);
throw(err);
}
}
);
}
/**
* Optimize SVG images for WEB.
*
* @param {import('svgo').Config} svgo_opts - Options passed to svgo.
* @param {Src2Dest[]} items - Array of SVG files (src:SVG, dest:SVG) to optimize.
*/
async function svg2svg(svgo_opts, items) {
items.forEach(
async (item) => {
try {
fs.mkdir(path.dirname(item.dest), { recursive: true }, (err) => {
if (err)
throw err;
});
const raw = fs.readFileSync(item.src, "utf8");
const opt = svgo(raw, svgo_opts);
fs.writeFileSync(item.dest, opt.data);
console.log(
`[svg2svg] optimized: ${item.dest} -- src: ${item.src}`
);
} catch (err) {
console.error(`ERROR: optimize src: ${item.src} -- ${err}`);
throw(err);
}
}
);
}
export { svg2png, svg2svg };

View File

@ -1,26 +0,0 @@
{{--
This is a EDGE https://edgejs.dev/ template to generate a HTML Jinja template
for the backend. Example output of this EDGE template:
- https://github.com/searxng/searxng/blob/master/searx/templates/simple/icons.html
--}}
{#
Catalog of SVG symbols that can be inserted into the HTML output of a Jinja
template. This file from:
client/simple/tools/icon_catalog.edge.html
#}
{%-
set catalog = {
@each((svg, name) in svg_catalog)
'{{{name}}}' : '{{{svg}}}',
@end
}
-%}
@each(macro in macros)
{% macro {{ macro.name }}(action, alt) -%}
{{ open_curly_brace }} catalog[action] | replace("{{__jinja_class_placeholder__}}", "{{ macro.class }}") | safe {{ close_curly_brace }}
{%- endmacro %}
@end

View File

@ -1,132 +0,0 @@
import fs from "fs";
import { resolve, dirname } from "path";
import { Edge } from 'edge.js';
import { optimize as svgo } from "svgo";
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const __jinja_class_placeholder__ = "__jinja_class_placeholder__";
// -- types
/**
* @typedef {object} IconSet - A set of icons
* @property {object[]} set - Array of SVG icons, where property name is the
* name of the icon and value is the src of the SVG (relative to base).
* @property {string} base - Folder in which the SVG src files are located.
* @property {import("svgo").Config} svgo_opts - svgo options for this set.
*/
/**
* @typedef {object} IconSVG - Mapping of icon name to SVG source file.
* @property {string} name - Name of the icon isource file.
* @property {string} src - Name of the destination file.
* @property {import("svgo").Config} svgo_opts - Options passed to svgo.
*/
/**
* @typedef {object} JinjaMacro - Arguments to create a jinja macro
* @property {string} name - Name of the jinja macro.
* @property {string} class - SVG's class name (value of XML class attribute)
*/
// -- functions
/**
* Generate a jinja template with a catalog of SVG icons that can be
* used in in other HTML jinja templates.
*
* @param {string} dest - filename of the generate jinja template.
* @param {JinjaMacro} macros - Jinja macros to create.
* @param {IconSVG[]} items - Array of SVG items.
*/
function jinja_svg_catalog(dest, macros, items) {
const svg_catalog = {};
const edge_template = resolve(__dirname, "jinja_svg_catalog.html.edge");
items.forEach(
(item) => {
/** @type {import("svgo").Config} */
// JSON.stringify & JSON.parse are used to create a deep copy of the
// item.svgo_opts object
const svgo_opts = JSON.parse(JSON.stringify(item.svgo_opts));
svgo_opts.plugins.push({
name: "addClassesToSVGElement",
params: {
classNames: [__jinja_class_placeholder__]
}}
);
try {
const raw = fs.readFileSync(item.src, "utf8");
const opt = svgo(raw, svgo_opts);
svg_catalog[item.name] = opt.data;
} catch (err) {
console.error(`ERROR: jinja_svg_catalog processing ${item.name} src: ${item.src} -- ${err}`);
throw(err);
}
}
);
fs.mkdir(dirname(dest), { recursive: true }, (err) => {
if (err) throw err;
});
const ctx = {
svg_catalog: svg_catalog,
macros: macros,
edge_template: edge_template,
__jinja_class_placeholder__: __jinja_class_placeholder__,
// see https://github.com/edge-js/edge/issues/162
open_curly_brace : "{{",
close_curly_brace : "}}"
};
const jinjatmpl = Edge.create().renderRawSync(
fs.readFileSync(edge_template, "utf-8"),
ctx
);
fs.writeFileSync(dest, jinjatmpl);
console.log(`[jinja_svg_catalog] created: ${dest}`);
}
/**
* Calls jinja_svg_catalog for a collection of icon sets where each set has its
* own parameters.
*
* @param {string} dest - filename of the generate jinja template.
* @param {JinjaMacro} macros - Jinja macros to create.
* @param {IconSet[]} sets - Array of SVG sets.
*/
function jinja_svg_sets(dest, macros, sets) {
/** @type IconSVG[] */
const items = [];
const all = [];
for (const obj of sets) {
for (const [name, file] of Object.entries(obj.set)) {
if (all.includes(name)) {
throw new Error(`ERROR: ${name} has already been defined`);
}
items.push({
name: name,
src: resolve(obj.base, file),
svgo_opts: obj.svgo_opts,
});
}
jinja_svg_catalog(dest, macros, items);
}
}
// -- exports
export {
jinja_svg_sets,
jinja_svg_catalog,
};

View File

@ -1,41 +0,0 @@
/**
* Custom vite plugins to build the web-client components of the simple theme.
*
* HINT:
*
* This is an inital implementation for the migration of the build process
* from grunt to vite. For fully support (vite: build & serve) more work is
* needed.
*/
import { svg2png } from "./img.js";
import { svg2svg } from "./img.js";
/**
* Vite plugin to convert a list of SVG files to PNG.
*
* @param {import('./img.js').Src2Dest} items - Array of SVG files (src: SVG, dest:PNG) to convert.
*/
function plg_svg2png(items) {
return {
name: 'searxng-simple-svg2png',
apply: 'build', // or 'serve'
async writeBundle() { svg2png(items); },
};
}
/**
* Vite plugin to optimize SVG images for WEB.
*
* @param {import('svgo').Config} svgo_opts - Options passed to svgo.
* @param {import('./img.js').Src2Dest} items - Array of SVG files (src:SVG, dest:SVG) to optimize.
*/
function plg_svg2svg(svgo_opts, items) {
return {
name: 'searxng-simple-svg2png',
apply: 'build', // or 'serve'
async writeBundle() { svg2svg(items, svgo_opts); },
};
}
export { plg_svg2png, plg_svg2svg };

View File

@ -1,185 +0,0 @@
/**
* CONFIG: https://vite.dev/config/
*/
import { resolve } from "node:path";
import { defineConfig } from "vite";
import stylelint from "vite-plugin-stylelint";
import { viteStaticCopy } from "vite-plugin-static-copy";
import { plg_svg2png } from "./tools/plg.js";
import { plg_svg2svg } from "./tools/plg.js";
const ROOT = "../.."; // root of the git reposetory
const PATH = {
dist: resolve(ROOT, "searx/static/themes/simple"),
// dist: resolve(ROOT, "client/simple/dist"),
src: "src",
modules: "node_modules",
brand: "src/brand",
static: resolve(ROOT, "client/simple/static"),
leaflet: resolve(ROOT, "client/simple/node_modules/leaflet/dist"),
templates: resolve(ROOT, "searx/templates/simple"),
};
const svg2svg_opts = {
plugins: [
{ name: "preset-default" },
"sortAttrs",
"convertStyleToAttrs",
]
};
const svg2svg_favicon_opts = {
plugins: [
{ name: "preset-default" },
"sortAttrs",
]
};
export default defineConfig({
root: PATH.src,
mode: "production",
// mode: "development",
// FIXME: missing CCS sourcemaps!!
// see: https://github.com/vitejs/vite/discussions/13845#discussioncomment-11992084
//
// what I have tried so far (see config below):
//
// - build.sourcemap
// - esbuild.sourcemap
// - css.preprocessorOptions.less.sourceMap
css: {
devSourcemap: true,
preprocessorOptions: {
less: {
// FIXME: missing CCS sourcemaps!!
sourceMap: {
outputSourceFiles: true,
sourceMapURL: (name) => { const s = name.split('/'); return s[s.length - 1] + '.map'; },
},
// env: 'development',
// relativeUrls: true,
// javascriptEnabled: true,
},
},
}, // end: css
esbuild : {
// FIXME: missing CCS sourcemaps!!
sourcemap: true
},
build: {
manifest: "manifest.json",
emptyOutDir: true,
assetsDir: "",
outDir: PATH.dist,
// FIXME: missing CCS sourcemaps!!
sourcemap: true,
// https://vite.dev/config/build-options.html#build-cssminify
cssMinify: true,
// cssMinify: "esbuild",
minify: "esbuild",
rollupOptions: {
input: {
// build CSS files
"css/searxng.min.css": PATH.src + "/less/style-ltr.less",
"css/searxng-rtl.min.css": PATH.src + "/less/style-rtl.less",
"css/rss.min.css": PATH.src + "/less/rss.less",
// build JS files
"js/searxng.head.min": PATH.src + "/js/searxng.head.js",
"js/searxng.min": PATH.src + "/js/searxng.js",
},
// file naming conventions / pathnames are relative to outDir (PATH.dist)
output: {
entryFileNames: "[name].js",
chunkFileNames: "[name].js",
assetFileNames: "[name].[ext]",
// Vite does not support "rollupOptions.output.sourcemap".
// Please use "build.sourcemap" instead.
// sourcemap: true,
},
},
}, // end: build
plugins: [
stylelint({
build: true,
emitWarningAsError: true,
fix: true,
}),
// Leaflet
viteStaticCopy({
targets: [
{ src: PATH.leaflet + "/leaflet.{js,js.map}", dest: PATH.dist + "/js" },
{ src: PATH.leaflet + "/images/*.png", dest: PATH.dist + "/css/images/" },
{ src: PATH.leaflet + "/*.{css,css.map}", dest: PATH.dist + "/css" },
{ src: PATH.static + "/**/*", dest: PATH.dist },
]
}),
// -- svg images
plg_svg2svg(
[
{ src: PATH.src + "/svg/empty_favicon.svg", dest: PATH.dist + "/img/empty_favicon.svg" },
{ src: PATH.src + "/svg/select-dark.svg", dest: PATH.dist + "/img/select-dark.svg" },
{ src: PATH.src + "/svg/select-light.svg", dest: PATH.dist + "/img/select-light.svg" },
],
svg2svg_opts,
),
// SearXNG brand (static)
plg_svg2png(
[
{ src: PATH.brand + "/searxng-wordmark.svg", dest: PATH.dist + "/img/favicon.png" },
{ src: PATH.brand + "/searxng.svg", dest: PATH.dist + "/img/searxng.png" },
],
),
// -- svg
plg_svg2svg(
[
{ src: PATH.brand + "/searxng.svg", dest: PATH.dist + "/img/searxng.svg" },
{ src: PATH.brand + "/img_load_error.svg", dest: PATH.dist + "/img/img_load_error.svg" },
],
svg2svg_opts,
),
// -- favicon
plg_svg2svg(
[ { src: PATH.brand + "/searxng-wordmark.svg", dest: PATH.dist + "/img/favicon.svg" } ],
svg2svg_favicon_opts,
),
// -- simple templates
plg_svg2svg(
[
{ src: PATH.brand + "/searxng-wordmark.svg", dest: PATH.templates + "/searxng-wordmark.min.svg" },
],
svg2svg_opts
),
] // end: plugins
});

View File

@ -1,100 +0,0 @@
FROM docker.io/library/python:3.13-slim AS builder
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential \
brotli \
# uwsgi
libpcre3-dev \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /usr/local/searxng/
COPY ./requirements.txt ./requirements.txt
RUN --mount=type=cache,id=pip,target=/root/.cache/pip python -m venv ./venv \
&& . ./venv/bin/activate \
&& pip install -r requirements.txt \
&& pip install "uwsgi~=2.0"
COPY ./searx/ ./searx/
ARG TIMESTAMP_SETTINGS=0
ARG TIMESTAMP_UWSGI=0
RUN python -m compileall -q searx \
&& touch -c --date=@$TIMESTAMP_SETTINGS ./searx/settings.yml \
&& touch -c --date=@$TIMESTAMP_UWSGI ./container/uwsgi.ini \
&& find /usr/local/searxng/searx/static \
\( -name '*.html' -o -name '*.css' -o -name '*.js' -o -name '*.svg' -o -name '*.ttf' -o -name '*.eot' \) \
-type f -exec gzip -9 -k {} + -exec brotli --best {} +
ARG SEARXNG_UID=977
ARG SEARXNG_GID=977
RUN grep -m1 root /etc/group > /tmp/.searxng.group \
&& grep -m1 root /etc/passwd > /tmp/.searxng.passwd \
&& echo "searxng:x:$SEARXNG_GID:" >> /tmp/.searxng.group \
&& echo "searxng:x:$SEARXNG_UID:$SEARXNG_GID:searxng:/usr/local/searxng:/bin/bash" >> /tmp/.searxng.passwd
FROM docker.io/library/python:3.13-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
# healthcheck
wget \
# uwsgi
libpcre3 \
libxml2 \
mailcap \
&& rm -rf /var/lib/apt/lists/*
COPY --chown=root:root --from=builder /tmp/.searxng.passwd /etc/passwd
COPY --chown=root:root --from=builder /tmp/.searxng.group /etc/group
ARG LABEL_DATE="0001-01-01T00:00:00Z"
ARG GIT_URL="unspecified"
ARG SEARXNG_GIT_VERSION="unspecified"
ARG LABEL_VCS_REF="unspecified"
ARG LABEL_VCS_URL="unspecified"
WORKDIR /usr/local/searxng/
COPY --chown=searxng:searxng --from=builder /usr/local/searxng/venv/ ./venv/
COPY --chown=searxng:searxng --from=builder /usr/local/searxng/searx/ ./searx/
COPY --chown=searxng:searxng ./container/ ./container/
LABEL org.opencontainers.image.authors="searxng <$GIT_URL>" \
org.opencontainers.image.created=$LABEL_DATE \
org.opencontainers.image.description="A privacy-respecting, hackable metasearch engine" \
org.opencontainers.image.documentation="https://github.com/searxng/searxng-docker" \
org.opencontainers.image.licenses="AGPL-3.0-or-later" \
org.opencontainers.image.revision=$LABEL_VCS_REF \
org.opencontainers.image.source=$LABEL_VCS_URL \
org.opencontainers.image.title="searxng" \
org.opencontainers.image.url=$LABEL_VCS_URL \
org.opencontainers.image.version=$SEARXNG_GIT_VERSION
ENV CONFIG_PATH=/etc/searxng \
DATA_PATH=/var/cache/searxng
ENV SEARXNG_VERSION=$SEARXNG_GIT_VERSION \
INSTANCE_NAME=searxng \
AUTOCOMPLETE="" \
BASE_URL="" \
BIND_ADDRESS=[::]:8080 \
MORTY_KEY="" \
MORTY_URL="" \
SEARXNG_SETTINGS_PATH=$CONFIG_PATH/settings.yml \
UWSGI_SETTINGS_PATH=$CONFIG_PATH/uwsgi.ini \
UWSGI_WORKERS=%k \
UWSGI_THREADS=4
VOLUME $CONFIG_PATH
VOLUME $DATA_PATH
EXPOSE 8080
HEALTHCHECK CMD wget --quiet --tries=1 --spider http://localhost:8080/healthz || exit 1
ENTRYPOINT ["/usr/local/searxng/container/docker-entrypoint.sh"]

View File

@ -1,106 +0,0 @@
# For armv7 architecture
FROM docker.io/library/python:3.13-slim AS builder
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential \
brotli \
# lxml
libxml2-dev \
libxslt1-dev \
zlib1g-dev \
# uwsgi
libpcre3-dev \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /usr/local/searxng/
COPY ./requirements.txt ./requirements.txt
RUN --mount=type=cache,id=pip,target=/root/.cache/pip python -m venv ./venv \
&& . ./venv/bin/activate \
&& pip install -r requirements.txt \
&& pip install "uwsgi~=2.0"
COPY ./searx/ ./searx/
ARG TIMESTAMP_SETTINGS=0
ARG TIMESTAMP_UWSGI=0
RUN python -m compileall -q searx \
&& touch -c --date=@$TIMESTAMP_SETTINGS ./searx/settings.yml \
&& touch -c --date=@$TIMESTAMP_UWSGI ./container/uwsgi.ini \
&& find /usr/local/searxng/searx/static \
\( -name '*.html' -o -name '*.css' -o -name '*.js' -o -name '*.svg' -o -name '*.ttf' -o -name '*.eot' \) \
-type f -exec gzip -9 -k {} + -exec brotli --best {} +
ARG SEARXNG_UID=977
ARG SEARXNG_GID=977
RUN grep -m1 root /etc/group > /tmp/.searxng.group \
&& grep -m1 root /etc/passwd > /tmp/.searxng.passwd \
&& echo "searxng:x:$SEARXNG_GID:" >> /tmp/.searxng.group \
&& echo "searxng:x:$SEARXNG_UID:$SEARXNG_GID:searxng:/usr/local/searxng:/bin/bash" >> /tmp/.searxng.passwd
FROM docker.io/library/python:3.13-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
# healthcheck
wget \
# lxml (ARMv7)
libxslt1.1 \
# uwsgi
libpcre3 \
libxml2 \
mailcap \
&& rm -rf /var/lib/apt/lists/*
COPY --chown=root:root --from=builder /tmp/.searxng.passwd /etc/passwd
COPY --chown=root:root --from=builder /tmp/.searxng.group /etc/group
ARG LABEL_DATE="0001-01-01T00:00:00Z"
ARG GIT_URL="unspecified"
ARG SEARXNG_GIT_VERSION="unspecified"
ARG LABEL_VCS_REF="unspecified"
ARG LABEL_VCS_URL="unspecified"
WORKDIR /usr/local/searxng/
COPY --chown=searxng:searxng --from=builder /usr/local/searxng/venv/ ./venv/
COPY --chown=searxng:searxng --from=builder /usr/local/searxng/searx/ ./searx/
COPY --chown=searxng:searxng ./container/ ./container/
LABEL org.opencontainers.image.authors="searxng <$GIT_URL>" \
org.opencontainers.image.created=$LABEL_DATE \
org.opencontainers.image.description="A privacy-respecting, hackable metasearch engine" \
org.opencontainers.image.documentation="https://github.com/searxng/searxng-docker" \
org.opencontainers.image.licenses="AGPL-3.0-or-later" \
org.opencontainers.image.revision=$LABEL_VCS_REF \
org.opencontainers.image.source=$LABEL_VCS_URL \
org.opencontainers.image.title="searxng" \
org.opencontainers.image.url=$LABEL_VCS_URL \
org.opencontainers.image.version=$SEARXNG_GIT_VERSION
ENV CONFIG_PATH=/etc/searxng \
DATA_PATH=/var/cache/searxng
ENV SEARXNG_VERSION=$SEARXNG_GIT_VERSION \
INSTANCE_NAME=searxng \
AUTOCOMPLETE="" \
BASE_URL="" \
BIND_ADDRESS=[::]:8080 \
SEARXNG_SETTINGS_PATH=$CONFIG_PATH/settings.yml \
UWSGI_SETTINGS_PATH=$CONFIG_PATH/uwsgi.ini \
UWSGI_WORKERS=%k \
UWSGI_THREADS=4
VOLUME $CONFIG_PATH
VOLUME $DATA_PATH
EXPOSE 8080
HEALTHCHECK CMD wget --quiet --tries=1 --spider http://localhost:8080/healthz || exit 1
ENTRYPOINT ["/usr/local/searxng/container/docker-entrypoint.sh"]

View File

@ -1,19 +0,0 @@
version: '3.8'
services:
searxng:
container_name: searxng
build: .
ports:
- "32768:8080" # Host:Container — change 8180 to whatever host port you want
restart: unless-stopped
environment:
- BASE_URL=https://search.bsllc.xyz # Optional if using a reverse proxy
volumes:
- ./searxng-settings:/etc/searxng # optional, only if you mount custom settings
networks:
- searxng_net
networks:
searxng_net:
driver: bridge

View File

@ -12,7 +12,10 @@ Environment variables:
INSTANCE_NAME settings.yml : general.instance_name INSTANCE_NAME settings.yml : general.instance_name
AUTOCOMPLETE settings.yml : search.autocomplete AUTOCOMPLETE settings.yml : search.autocomplete
BASE_URL settings.yml : server.base_url BASE_URL settings.yml : server.base_url
MORTY_URL settings.yml : result_proxy.url
MORTY_KEY settings.yml : result_proxy.key
BIND_ADDRESS uwsgi bind to the specified TCP socket using HTTP protocol.
Default value: ${DEFAULT_BIND_ADDRESS}
Volume: Volume:
/etc/searxng the docker entry point copies settings.yml and uwsgi.ini in /etc/searxng the docker entry point copies settings.yml and uwsgi.ini in
this directory (see the -f command line option)" this directory (see the -f command line option)"
@ -20,6 +23,9 @@ Volume:
EOF EOF
} }
export DEFAULT_BIND_ADDRESS="0.0.0.0:8080"
export BIND_ADDRESS="${BIND_ADDRESS:-${DEFAULT_BIND_ADDRESS}}"
# Parse command line # Parse command line
FORCE_CONF_UPDATE=0 FORCE_CONF_UPDATE=0
DRY_RUN=0 DRY_RUN=0
@ -42,7 +48,15 @@ do
esac esac
done done
echo "SearXNG version $SEARXNG_VERSION" get_searxng_version(){
su searxng -c \
'python3 -c "import six; import searx.version; six.print_(searx.version.VERSION_STRING)"' \
2>/dev/null
}
SEARXNG_VERSION="$(get_searxng_version)"
export SEARXNG_VERSION
echo "SearXNG version ${SEARXNG_VERSION}"
# helpers to update the configuration files # helpers to update the configuration files
patch_uwsgi_settings() { patch_uwsgi_settings() {
@ -67,8 +81,22 @@ patch_searxng_settings() {
-e "s|base_url: false|base_url: ${BASE_URL}|g" \ -e "s|base_url: false|base_url: ${BASE_URL}|g" \
-e "s/instance_name: \"SearXNG\"/instance_name: \"${INSTANCE_NAME}\"/g" \ -e "s/instance_name: \"SearXNG\"/instance_name: \"${INSTANCE_NAME}\"/g" \
-e "s/autocomplete: \"\"/autocomplete: \"${AUTOCOMPLETE}\"/g" \ -e "s/autocomplete: \"\"/autocomplete: \"${AUTOCOMPLETE}\"/g" \
-e "s/ultrasecretkey/$(head -c 24 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9')/g" \ -e "s/ultrasecretkey/$(openssl rand -hex 32)/g" \
"${CONF}" "${CONF}"
# Morty configuration
if [ -n "${MORTY_KEY}" ] && [ -n "${MORTY_URL}" ]; then
sed -i -e "s/image_proxy: false/image_proxy: true/g" \
"${CONF}"
cat >> "${CONF}" <<-EOF
# Morty configuration
result_proxy:
url: ${MORTY_URL}
key: !!binary "${MORTY_KEY}"
EOF
fi
} }
update_conf() { update_conf() {
@ -107,8 +135,32 @@ update_conf() {
fi fi
} }
# searx compatibility: copy /etc/searx/* to /etc/searxng/*
SEARX_CONF=0
if [ -f "/etc/searx/settings.yml" ]; then
if [ ! -f "${SEARXNG_SETTINGS_PATH}" ]; then
printf '⚠️ /etc/searx/settings.yml is copied to /etc/searxng\n'
cp "/etc/searx/settings.yml" "${SEARXNG_SETTINGS_PATH}"
fi
SEARX_CONF=1
fi
if [ -f "/etc/searx/uwsgi.ini" ]; then
printf '⚠️ /etc/searx/uwsgi.ini is ignored. Use the volume /etc/searxng\n'
SEARX_CONF=1
fi
if [ "$SEARX_CONF" -eq "1" ]; then
printf '⚠️ The deprecated volume /etc/searx is mounted. Please update your configuration to use /etc/searxng ⚠️\n'
cat << EOF > /etc/searx/deprecated_volume_read_me.txt
This Docker image uses the volume /etc/searxng
Update your configuration:
* remove uwsgi.ini (or very carefully update your existing uwsgi.ini using https://github.com/searxng/searxng/blob/master/dockerfiles/uwsgi.ini )
* mount /etc/searxng instead of /etc/searx
EOF
fi
# end of searx compatibility
# make sure there are uwsgi settings # make sure there are uwsgi settings
update_conf "${FORCE_CONF_UPDATE}" "${UWSGI_SETTINGS_PATH}" "/usr/local/searxng/container/uwsgi.ini" "patch_uwsgi_settings" update_conf "${FORCE_CONF_UPDATE}" "${UWSGI_SETTINGS_PATH}" "/usr/local/searxng/dockerfiles/uwsgi.ini" "patch_uwsgi_settings"
# make sure there are searxng settings # make sure there are searxng settings
update_conf "${FORCE_CONF_UPDATE}" "${SEARXNG_SETTINGS_PATH}" "/usr/local/searxng/searx/settings.yml" "patch_searxng_settings" update_conf "${FORCE_CONF_UPDATE}" "${SEARXNG_SETTINGS_PATH}" "/usr/local/searxng/searx/settings.yml" "patch_searxng_settings"
@ -119,8 +171,8 @@ if [ $DRY_RUN -eq 1 ]; then
exit exit
fi fi
printf 'Listen on %s\n' "${BIND_ADDRESS}" unset MORTY_KEY
# Start uwsgi # Start uwsgi
# TODO: "--http-socket" will be removed in the future (see uwsgi.ini.new config file): https://github.com/searxng/searxng/pull/4578 printf 'Listen on %s\n' "${BIND_ADDRESS}"
exec /usr/local/searxng/venv/bin/uwsgi --http-socket "${BIND_ADDRESS}" "${UWSGI_SETTINGS_PATH}" exec su-exec searxng:searxng uwsgi --master --http-socket "${BIND_ADDRESS}" "${UWSGI_SETTINGS_PATH}"

View File

@ -1,19 +1,11 @@
[uwsgi] [uwsgi]
# Listening address
# default value: [::]:8080 (see Dockerfile)
http-socket = $(BIND_ADDRESS)
# Who will run the code # Who will run the code
uid = searxng uid = searxng
gid = searxng gid = searxng
# Number of workers (usually CPU count) # Number of workers (usually CPU count)
# default value: %k (= number of CPU core, see Dockerfile) workers = %k
workers = $(UWSGI_WORKERS) threads = 4
# Number of threads per worker
# default value: 4 (see Dockerfile)
threads = $(UWSGI_THREADS)
# The right granted on the created socket # The right granted on the created socket
chmod-socket = 666 chmod-socket = 666
@ -21,6 +13,7 @@ chmod-socket = 666
# Plugin to use and interpreter config # Plugin to use and interpreter config
single-interpreter = true single-interpreter = true
master = true master = true
plugin = python3
lazy-apps = true lazy-apps = true
enable-threads = true enable-threads = true
@ -45,11 +38,9 @@ buffer-size = 8192
# See https://github.com/searx/searx-docker/issues/24 # See https://github.com/searx/searx-docker/issues/24
add-header = Connection: close add-header = Connection: close
# Follow SIGTERM convention
# See https://github.com/searxng/searxng/issues/3427
die-on-term
# uwsgi serves the static files # uwsgi serves the static files
# expires set to one year since there are hashes
static-map = /static=/usr/local/searxng/searx/static static-map = /static=/usr/local/searxng/searx/static
static-expires = /* 31557600
static-gzip-all = True static-gzip-all = True
offload-threads = %k offload-threads = %k

View File

@ -69,6 +69,10 @@ Sample response
{ {
"enabled": true, "enabled": true,
"name": "HTTPS rewrite" "name": "HTTPS rewrite"
},
{
"enabled": false,
"name": "Vim-like hotkeys"
} }
], ],
"safe_search": 0 "safe_search": 0
@ -84,9 +88,9 @@ HTML of the site. URL of the SearXNG instance and values are customizable.
.. code:: html .. code:: html
<form method="post" action="https://example.org/"> <form method="post" action="https://example.org/">
<!-- search --> <input type="text" name="q"> <!-- search --> <input type="text" name="q" />
<!-- categories --> <input type="hidden" name="categories" value="general,social media"> <!-- categories --> <input type="hidden" name="categories" value="general,social media" />
<!-- language --> <input type="hidden" name="lang" value="all"> <!-- language --> <input type="hidden" name="lang" value="all" />
<!-- locale --> <input type="hidden" name="locale" value="en"> <!-- locale --> <input type="hidden" name="locale" value="en" />
<!-- date filter --> <input type="hidden" name="time_range" value="month"> <!-- date filter --> <input type="hidden" name="time_range" value="month" />
</form> </form>

View File

@ -6,7 +6,7 @@ digraph G {
browser [label="browser", shape=tab, fillcolor=aliceblue]; browser [label="browser", shape=tab, fillcolor=aliceblue];
rp [label="reverse proxy"]; rp [label="reverse proxy"];
static [label="static files", shape=folder, href="url to configure static files", fillcolor=lightgray]; static [label="static files", shape=folder, href="url to configure static files", fillcolor=lightgray];
uwsgi [label="uwsgi", shape=parallelogram href="https://docs.searxng.org/utils/searxng.sh.html"] uwsgi [label="uwsgi", shape=parallelogram href="https://docs.searxng.org/utils/searx.sh.html"]
redis [label="redis DB", shape=cylinder]; redis [label="redis DB", shape=cylinder];
searxng1 [label="SearXNG #1", fontcolor=blue3]; searxng1 [label="SearXNG #1", fontcolor=blue3];
searxng2 [label="SearXNG #2", fontcolor=blue3]; searxng2 [label="SearXNG #2", fontcolor=blue3];

View File

@ -15,8 +15,6 @@ Administrator documentation
installation-apache installation-apache
update-searxng update-searxng
answer-captcha answer-captcha
searx.favicons
searx.limiter
api api
architecture architecture
plugins plugins

View File

@ -190,7 +190,7 @@ Debian:
Apache modules Apache modules
-------------- --------------
To load additional modules, in most distributions you have to uncomment the To load additional modules, in most distributions you have to un-comment the
lines with the corresponding LoadModule_ directive, except in :ref:`Debian's lines with the corresponding LoadModule_ directive, except in :ref:`Debian's
Apache layout`. Apache layout`.

View File

@ -92,9 +92,6 @@ instance using `docker run <https://docs.docker.com/engine/reference/run/>`_:
searxng/searxng searxng/searxng
2f998.... # container's ID 2f998.... # container's ID
The environment variables UWSGI_WORKERS and UWSGI_THREADS overwrite the default
number of UWSGI processes and UWSGI threads specified in `/etc/searxng/uwsgi.ini`.
Open your WEB browser and visit the URL: Open your WEB browser and visit the URL:
.. code:: sh .. code:: sh
@ -145,6 +142,13 @@ shell inside container
- `How to make bash scripts work in dash <http://mywiki.wooledge.org/Bashism>`_ - `How to make bash scripts work in dash <http://mywiki.wooledge.org/Bashism>`_
- `Checking for Bashisms <https://dev.to/bowmanjd/writing-bash-scripts-that-are-not-only-bash-checking-for-bashisms-and-testing-with-dash-1bli>`_ - `Checking for Bashisms <https://dev.to/bowmanjd/writing-bash-scripts-that-are-not-only-bash-checking-for-bashisms-and-testing-with-dash-1bli>`_
Like in many other distributions, Alpine's `/bin/sh
<https://wiki.ubuntu.com/DashAsBinSh>`__ is :man:`dash`. Dash is meant to be
`POSIX-compliant <https://pubs.opengroup.org/onlinepubs/9699919799>`__.
Compared to debian, in the Alpine image :man:`bash` is not installed. The
:origin:`dockerfiles/docker-entrypoint.sh` script is checked *against dash*
(``make tests.shell``).
To open a shell inside the container: To open a shell inside the container:
.. code:: sh .. code:: sh
@ -181,10 +185,10 @@ Command line
<https://docs.docker.com/engine/reference/run/#foreground>`__. <https://docs.docker.com/engine/reference/run/#foreground>`__.
In the :origin:`Dockerfile` the ENTRYPOINT_ is defined as In the :origin:`Dockerfile` the ENTRYPOINT_ is defined as
:origin:`container/docker-entrypoint.sh` :origin:`dockerfiles/docker-entrypoint.sh`
.. code:: sh .. code:: sh
docker run --rm -it searxng/searxng -h docker run --rm -it searxng/searxng -h
.. program-output:: ../container/docker-entrypoint.sh -h .. program-output:: ../dockerfiles/docker-entrypoint.sh -h

View File

@ -96,7 +96,7 @@ Modify the ``/etc/searxng/settings.yml`` to your needs:
.. literalinclude:: ../../utils/templates/etc/searxng/settings.yml .. literalinclude:: ../../utils/templates/etc/searxng/settings.yml
:language: yaml :language: yaml
:end-before: # preferences: :end-before: # hostname_replace:
To see the entire file jump to :origin:`utils/templates/etc/searxng/settings.yml` To see the entire file jump to :origin:`utils/templates/etc/searxng/settings.yml`
@ -104,7 +104,7 @@ Modify the ``/etc/searxng/settings.yml`` to your needs:
.. literalinclude:: ../../searx/settings.yml .. literalinclude:: ../../searx/settings.yml
:language: yaml :language: yaml
:end-before: # hostnames: :end-before: # hostname_replace:
To see the entire file jump to :origin:`searx/settings.yml` To see the entire file jump to :origin:`searx/settings.yml`

View File

@ -1,13 +1,16 @@
.. _plugins admin: .. _plugins generic:
=============== ===============
List of plugins Plugins builtin
=============== ===============
Further reading .. .. sidebar:: Further reading ..
- :ref:`SearXNG settings <settings plugins>` - :ref:`dev plugin`
- :ref:`dev plugin`
Configuration defaults (at built time):
:DO: Default on
.. _configured plugins: .. _configured plugins:
@ -19,13 +22,18 @@ Further reading ..
:widths: 3 1 9 :widths: 3 1 9
* - Name * - Name
- Active - DO
- Description - Description
{% for plg in plugins %} JS & CSS dependencies
* - {{plg.info.name}} {% for plgin in plugins %}
- {{(plg.active and "yes") or "no"}}
- {{plg.info.description}} * - {{plgin.name}}
- {{(plgin.default_on and "y") or ""}}
- {{plgin.description}}
{% for dep in (plgin.js_dependencies + plgin.css_dependencies) %}
| ``{{dep}}`` {% endfor %}
{% endfor %} {% endfor %}

View File

@ -1,253 +0,0 @@
.. _favicons:
========
Favicons
========
.. sidebar:: warning
Don't activate the favicons before reading the documentation.
.. contents::
:depth: 2
:local:
:backlinks: entry
Activating the favicons in SearXNG is very easy, but this **generates a
significantly higher load** in the client/server communication and increases
resources needed on the server.
To mitigate these disadvantages, various methods have been implemented,
including a *cache*. The cache must be parameterized according to your own
requirements and maintained regularly.
To activate favicons in SearXNG's result list, set a default
``favicon_resolver`` in the :ref:`search <settings search>` settings:
.. code:: yaml
search:
favicon_resolver: "duckduckgo"
By default and without any extensions, SearXNG serves these resolvers:
- ``duckduckgo``
- ``allesedv``
- ``google``
- ``yandex``
With the above setting favicons are displayed, the user has the option to
deactivate this feature in his settings. If the user is to have the option of
selecting from several *resolvers*, a further setting is required / but this
setting will be discussed :ref:`later <register resolvers>` in this article,
first we have to setup the favicons cache.
Infrastructure
==============
The infrastructure for providing the favicons essentially consists of three
parts:
- :py:obj:`Favicons-Proxy <.favicons.proxy>` (aka *proxy*)
- :py:obj:`Favicons-Resolvers <.favicons.resolvers>` (aka *resolver*)
- :py:obj:`Favicons-Cache <.favicons.cache>` (aka *cache*)
To protect the privacy of users, the favicons are provided via a *proxy*. This
*proxy* is automatically activated with the above activation of a *resolver*.
Additional requests are required to provide the favicons: firstly, the *proxy*
must process the incoming requests and secondly, the *resolver* must make
outgoing requests to obtain the favicons from external sources.
A *cache* has been developed to massively reduce both, incoming and outgoing
requests. This *cache* is also activated automatically with the above
activation of a *resolver*. In its defaults, however, the *cache* is minimal
and not well suitable for a production environment!
.. _favicon cache setup:
Setting up the cache
====================
To parameterize the *cache* and more settings of the favicons infrastructure, a
TOML_ configuration is created in the file ``/etc/searxng/favicons.toml``.
.. code:: toml
[favicons]
cfg_schema = 1 # config's schema version no.
[favicons.cache]
db_url = "/var/cache/searxng/faviconcache.db" # default: "/tmp/faviconcache.db"
LIMIT_TOTAL_BYTES = 2147483648 # 2 GB / default: 50 MB
# HOLD_TIME = 5184000 # 60 days / default: 30 days
# BLOB_MAX_BYTES = 40960 # 40 KB / default 20 KB
# MAINTENANCE_MODE = "off" # default: "auto"
# MAINTENANCE_PERIOD = 600 # 10min / default: 1h
:py:obj:`cfg_schema <.FaviconConfig.cfg_schema>`:
Is required to trigger any processes required for future upgrades / don't
change it.
:py:obj:`cache.db_url <.FaviconCacheConfig.db_url>`:
The path to the (SQLite_) database file. The default path is in the `/tmp`_
folder, which is deleted on every reboot and is therefore unsuitable for a
production environment. The FHS_ provides the folder `/var/cache`_ for the
cache of applications, so a suitable storage location of SearXNG's caches is
folder ``/var/cache/searxng``.
In a standard installation (compare :ref:`create searxng user`), the folder
must be created and the user under which the SearXNG process is running must
be given write permission to this folder.
.. code:: bash
$ sudo mkdir /var/cache/searxng
$ sudo chown root:searxng /var/cache/searxng/
$ sudo chmod g+w /var/cache/searxng/
In container systems, a volume should be mounted for this folder. Check
whether the process in the container has read/write access to the mounted
folder.
:py:obj:`cache.LIMIT_TOTAL_BYTES <.FaviconCacheConfig.LIMIT_TOTAL_BYTES>`:
Maximum of bytes stored in the cache of all blobs. The limit is only reached
at each maintenance interval after which the oldest BLOBs are deleted; the
limit is exceeded during the maintenance period.
.. attention::
If the maintenance period is too long or maintenance is switched
off completely, the cache grows uncontrollably.
SearXNG hosters can change other parameters of the cache as required:
- :py:obj:`cache.HOLD_TIME <.FaviconCacheConfig.HOLD_TIME>`
- :py:obj:`cache.BLOB_MAX_BYTES <.FaviconCacheConfig.BLOB_MAX_BYTES>`
Maintenance of the cache
------------------------
Regular maintenance of the cache is required! By default, regular maintenance
is triggered automatically as part of the client requests:
- :py:obj:`cache.MAINTENANCE_MODE <.FaviconCacheConfig.MAINTENANCE_MODE>` (default ``auto``)
- :py:obj:`cache.MAINTENANCE_PERIOD <.FaviconCacheConfig.MAINTENANCE_PERIOD>` (default ``6000`` / 1h)
As an alternative to maintenance as part of the client request process, it is
also possible to carry out maintenance using an external process. For example,
by creating a :man:`crontab` entry for maintenance:
.. code:: bash
$ python -m searx.favicons cache maintenance
The following command can be used to display the state of the cache:
.. code:: bash
$ python -m searx.favicons cache state
.. _favicon proxy setup:
Proxy configuration
===================
Most of the options of the :py:obj:`Favicons-Proxy <.favicons.proxy>` are
already set sensibly with settings from the :ref:`settings.yml <searxng
settings.yml>` and should not normally be adjusted.
.. code:: toml
[favicons.proxy]
max_age = 5184000 # 60 days / default: 7 days (604800 sec)
:py:obj:`max_age <.FaviconProxyConfig.max_age>`:
The `HTTP Cache-Control max-age`_ response directive indicates that the
response remains fresh until N seconds after the response is generated. This
setting therefore determines how long a favicon remains in the client's cache.
As a rule, in the favicons infrastructure of SearXNG's this setting only
affects favicons whose byte size exceeds :ref:`BLOB_MAX_BYTES <favicon cache
setup>` (the other favicons that are already in the cache are embedded as
`data URL`_ in the :py:obj:`generated HTML <.favicons.proxy.favicon_url>`,
which can greatly reduce the number of additional requests).
.. _register resolvers:
Register resolvers
------------------
A :py:obj:`resolver <.favicon.resolvers>` is a function that obtains the favicon
from an external source. The resolver functions available to the user are
registered with their fully qualified name (FQN_) in a ``resolver_map``.
If no ``resolver_map`` is defined in the ``favicon.toml``, the favicon
infrastructure of SearXNG generates this ``resolver_map`` automatically
depending on the ``settings.yml``. SearXNG would automatically generate the
following TOML configuration from the following YAML configuration:
.. code:: yaml
search:
favicon_resolver: "duckduckgo"
.. code:: toml
[favicons.proxy.resolver_map]
"duckduckgo" = "searx.favicons.resolvers.duckduckgo"
If this automatism is not desired, then (and only then) a separate
``resolver_map`` must be created. For example, to give the user two resolvers to
choose from, the following configuration could be used:
.. code:: toml
[favicons.proxy.resolver_map]
"duckduckgo" = "searx.favicons.resolvers.duckduckgo"
"allesedv" = "searx.favicons.resolvers.allesedv"
# "google" = "searx.favicons.resolvers.google"
# "yandex" = "searx.favicons.resolvers.yandex"
.. note::
With each resolver, the resource requirement increases significantly.
The number of resolvers increases:
- the number of incoming/outgoing requests and
- the number of favicons to be stored in the cache.
In the following we list the resolvers available in the core of SearXNG, but via
the FQN_ it is also possible to implement your own resolvers and integrate them
into the *proxy*:
- :py:obj:`searx.favicons.resolvers.duckduckgo`
- :py:obj:`searx.favicons.resolvers.allesedv`
- :py:obj:`searx.favicons.resolvers.google`
- :py:obj:`searx.favicons.resolvers.yandex`
.. _SQLite:
https://www.sqlite.org/
.. _FHS:
https://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html
.. _`/var/cache`:
https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch05s05.html
.. _`/tmp`:
https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch03s18.html
.. _TOML:
https://toml.io/en/
.. _HTTP Cache-Control max-age:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#response_directives
.. _data URL:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs
.. _FQN: https://en.wikipedia.org/wiki/Fully_qualified_name

View File

@ -1,17 +0,0 @@
.. _limiter:
=======
Limiter
=======
.. sidebar:: info
The limiter requires a :ref:`Redis <settings redis>` database.
.. contents::
:depth: 2
:local:
:backlinks: entry
.. automodule:: searx.limiter
:members:

View File

@ -1,5 +1,3 @@
.. _searxng settings.yml:
======== ========
Settings Settings
======== ========
@ -13,7 +11,7 @@ Settings
:maxdepth: 2 :maxdepth: 2
settings settings
settings_engines settings_engine
settings_brand settings_brand
settings_general settings_general
settings_search settings_search
@ -22,6 +20,6 @@ Settings
settings_redis settings_redis
settings_outgoing settings_outgoing
settings_categories_as_tabs settings_categories_as_tabs
settings_plugins

View File

@ -59,7 +59,7 @@ and can relied on the default configuration :origin:`searx/settings.yml` using:
use_default_settings: true use_default_settings: true
server: server:
secret_key: "ultrasecretkey" # change this! secret_key: "ultrasecretkey" # change this!
bind_address: "[::]" bind_address: "0.0.0.0"
``engines:`` ``engines:``
With ``use_default_settings: true``, each settings can be override in a With ``use_default_settings: true``, each settings can be override in a

View File

@ -1,30 +1,14 @@
.. _settings engines: .. _settings engine:
============ ===========
``engines:`` ``engine:``
============ ===========
.. sidebar:: Further reading .. .. sidebar:: Further reading ..
- :ref:`configured engines` - :ref:`configured engines`
- :ref:`engines-dev` - :ref:`engines-dev`
In the section ``engines:`` is a list of the engines that are to be made
available in the instance. Each list entry is in turn a key/value mapping.
.. code:: yaml
engines:
- name: dummy.online
engine: dummy
..
- name: dummy.offline
engine: dummy-offline
..
..
In the code example below a *full fledged* example of a YAML setup from a dummy In the code example below a *full fledged* example of a YAML setup from a dummy
engine is shown. Most of the options have a default value or even are optional. engine is shown. Most of the options have a default value or even are optional.
@ -35,7 +19,7 @@ engine is shown. Most of the options have a default value or even are optional.
.. code:: yaml .. code:: yaml
- name: example - name: example engine
engine: example engine: example
shortcut: demo shortcut: demo
base_url: 'https://{language}.example.com/' base_url: 'https://{language}.example.com/'
@ -148,8 +132,6 @@ engine is shown. Most of the options have a default value or even are optional.
``display_error_messages`` : default ``true`` ``display_error_messages`` : default ``true``
When an engine returns an error, the message is displayed on the user interface. When an engine returns an error, the message is displayed on the user interface.
.. _engine network:
``network`` : optional ``network`` : optional
Use the network configuration from another engine. Use the network configuration from another engine.
In addition, there are two default networks: In addition, there are two default networks:
@ -222,7 +204,7 @@ Example configuration to restrict access to the Arch Linux Wiki engine:
tokens: [ 'my-secret-token' ] tokens: [ 'my-secret-token' ]
Unless a user has configured the right token, the engine is going to be hidden Unless a user has configured the right token, the engine is going to be hidden
from them. It is not going to be included in the list of engines on the from him/her. It is not going to be included in the list of engines on the
Preferences page and in the output of `/config` REST API call. Preferences page and in the output of `/config` REST API call.
Tokens can be added to one's configuration on the Preferences page under "Engine Tokens can be added to one's configuration on the Preferences page under "Engine
@ -259,3 +241,4 @@ Example configuration in settings.yml for a German and English speaker:
When searching, the default google engine will return German results and When searching, the default google engine will return German results and
"google english" will return English results. "google english" will return English results.

View File

@ -13,17 +13,10 @@
donation_url: false donation_url: false
contact_url: false contact_url: false
enable_metrics: true enable_metrics: true
open_metrics: ''
``debug`` : ``$SEARXNG_DEBUG`` ``debug`` : ``$SEARXNG_DEBUG``
In debug mode, the server provides an interactive debugger, will reload when Allow a more detailed log if you run SearXNG directly. Display *detailed* error
code is changed and activates a verbose logging. messages in the browser too, so this must be deactivated in production.
.. attention::
The debug setting is intended for local development server. Don't
activate debug (don't use a development server) when deploying to
production.
``donation_url`` : ``donation_url`` :
Set value to ``true`` to use your own donation page written in the Set value to ``true`` to use your own donation page written in the
@ -39,10 +32,3 @@
``enable_metrics``: ``enable_metrics``:
Enabled by default. Record various anonymous metrics available at ``/stats``, Enabled by default. Record various anonymous metrics available at ``/stats``,
``/stats/errors`` and ``/preferences``. ``/stats/errors`` and ``/preferences``.
``open_metrics``:
Disabled by default. Set to a secret password to expose an
`OpenMetrics API <https://github.com/prometheus/OpenMetrics>`_ at ``/metrics``,
e.g. for usage with Prometheus. The ``/metrics`` endpoint is using HTTP Basic Auth,
where the password is the value of ``open_metrics`` set above. The username used for
Basic Auth can be randomly chosen as only the password is being validated.

View File

@ -43,7 +43,7 @@ Communication with search engines.
Global timeout of the requests made to others engines in seconds. A bigger Global timeout of the requests made to others engines in seconds. A bigger
timeout will allow to wait for answers from slow engines, but in consequence timeout will allow to wait for answers from slow engines, but in consequence
will slow SearXNG reactivity (the result page may take the time specified in the will slow SearXNG reactivity (the result page may take the time specified in the
timeout to load). Can be override by ``timeout`` in the :ref:`settings engines`. timeout to load). Can be override by ``timeout`` in the :ref:`settings engine`.
``useragent_suffix`` : ``useragent_suffix`` :
Suffix to the user-agent SearXNG uses to send requests to others engines. If an Suffix to the user-agent SearXNG uses to send requests to others engines. If an
@ -105,6 +105,6 @@ Communication with search engines.
``using_tor_proxy`` : ``using_tor_proxy`` :
Using tor proxy (``true``) or not (``false``) for all engines. The default is Using tor proxy (``true``) or not (``false``) for all engines. The default is
``false`` and can be overwritten in the :ref:`settings engines` ``false`` and can be overwritten in the :ref:`settings engine`

View File

@ -1,77 +0,0 @@
.. _settings plugins:
============
``plugins:``
============
.. attention::
The ``enabled_plugins:`` section in SearXNG's settings no longer exists.
There is no longer a distinction between built-in and external plugin, all
plugins are registered via the settings in the ``plugins:`` section.
.. sidebar:: Further reading ..
- :ref:`plugins admin`
- :ref:`dev plugin`
In SearXNG, plugins can be registered in the :py:obj:`PluginStore
<searx.plugins.PluginStorage>` via a fully qualified class name.
A configuration (:py:obj:`PluginCfg <searx.plugins.PluginCfg>`) can be
transferred to the plugin, e.g. to activate it by default / *opt-in* or
*opt-out* from user's point of view.
Please note that some plugins, such as the :ref:`hostnames plugin` plugin,
require further configuration before they can be made available for selection.
built-in plugins
================
The built-in plugins are all located in the namespace `searx.plugins`.
.. code:: yaml
plugins:
searx.plugins.calculator.SXNGPlugin:
active: true
searx.plugins.hash_plugin.SXNGPlugin:
active: true
searx.plugins.self_info.SXNGPlugin:
active: true
searx.plugins.tracker_url_remover.SXNGPlugin:
active: true
searx.plugins.unit_converter.SXNGPlugin:
active: true
searx.plugins.ahmia_filter.SXNGPlugin:
active: true
searx.plugins.hostnames.SXNGPlugin:
active: true
searx.plugins.oa_doi_rewrite.SXNGPlugin:
active: false
searx.plugins.tor_check.SXNGPlugin:
active: false
.. _settings external_plugins:
external plugins
================
.. _Only show green hosted results:
https://github.com/return42/tgwf-searx-plugins/
SearXNG supports *external plugins* / there is no need to install one, SearXNG
runs out of the box.
- `Only show green hosted results`_
- ..

View File

@ -9,10 +9,8 @@
search: search:
safe_search: 0 safe_search: 0
autocomplete: "" autocomplete: ""
favicon_resolver: ""
default_lang: "" default_lang: ""
ban_time_on_fail: 5 ban_time_on_fail: 5
max_page: 0
max_ban_time_on_fail: 120 max_ban_time_on_fail: 120
suspended_times: suspended_times:
SearxEngineAccessDenied: 86400 SearxEngineAccessDenied: 86400
@ -34,34 +32,22 @@
``autocomplete``: ``autocomplete``:
Existing autocomplete backends, leave blank to turn it off. Existing autocomplete backends, leave blank to turn it off.
- ``360search``
- ``baidu``
- ``brave``
- ``dbpedia`` - ``dbpedia``
- ``duckduckgo`` - ``duckduckgo``
- ``google`` - ``google``
- ``mwmbl`` - ``mwmbl``
- ``quark`` - ``startpage``
- ``qwant``
- ``seznam``
- ``sogou``
- ``stract``
- ``swisscows`` - ``swisscows``
- ``qwant``
- ``wikipedia`` - ``wikipedia``
- ``yandex``
``favicon_resolver``:
To activate favicons in SearXNG's result list select a default
favicon-resolver, leave blank to turn off the feature. Don't activate the
favicons before reading the :ref:`Favicons documentation <favicons>`.
``default_lang``: ``default_lang``:
Default search language - leave blank to detect from browser information or Default search language - leave blank to detect from browser information or
use codes from :origin:`searx/sxng_locales.py`. use codes from :origin:`searx/languages.py`.
``languages``: ``languages``:
List of available languages - leave unset to use all codes from List of available languages - leave unset to use all codes from
:origin:`searx/sxng_locales.py`. Otherwise list codes of available languages. :origin:`searx/languages.py`. Otherwise list codes of available languages.
The ``all`` value is shown as the ``Default language`` in the user interface The ``all`` value is shown as the ``Default language`` in the user interface
(in most cases, it is meant to send the query without a language parameter ; (in most cases, it is meant to send the query without a language parameter ;
in some cases, it means the English language) Example: in some cases, it means the English language) Example:
@ -77,11 +63,6 @@
- fr - fr
- fr-BE - fr-BE
``max_page``:
If engine supports paging, 0 means unlimited numbers of pages. The value
is only applied if the engine itself does not have a max value that is
lower than this one.
``ban_time_on_fail``: ``ban_time_on_fail``:
Ban time in seconds after engine errors. Ban time in seconds after engine errors.

View File

@ -12,52 +12,41 @@
bind_address: "127.0.0.1" bind_address: "127.0.0.1"
secret_key: "ultrasecretkey" # change this! secret_key: "ultrasecretkey" # change this!
limiter: false limiter: false
public_instance: false
image_proxy: false image_proxy: false
method: "POST"
default_http_headers: default_http_headers:
X-Content-Type-Options : nosniff X-Content-Type-Options : nosniff
X-XSS-Protection : 1; mode=block
X-Download-Options : noopen X-Download-Options : noopen
X-Robots-Tag : noindex, nofollow X-Robots-Tag : noindex, nofollow
Referrer-Policy : no-referrer Referrer-Policy : no-referrer
``base_url`` : ``$SEARXNG_BASE_URL``
The base URL where SearXNG is deployed. Used to create correct inbound links.
``port`` & ``bind_address``: ``$SEARXNG_PORT`` & ``$SEARXNG_BIND_ADDRESS`` ``base_url`` : ``$SEARXNG_URL`` :ref:`buildenv <make buildenv>`
The base URL where SearXNG is deployed. Used to create correct inbound links.
If you change the value, don't forget to rebuild instance's environment
(:ref:`utils/brand.env <make buildenv>`)
``port`` & ``bind_address``: ``$SEARXNG_PORT`` & ``$SEARXNG_BIND_ADDRESS`` :ref:`buildenv <make buildenv>`
Port number and *bind address* of the SearXNG web application if you run it Port number and *bind address* of the SearXNG web application if you run it
directly using ``python searx/webapp.py``. Doesn't apply to a SearXNG directly using ``python searx/webapp.py``. Doesn't apply to a SearXNG
services running behind a proxy and using socket communications. services running behind a proxy and using socket communications. If you
change the value, don't forget to rebuild instance's environment
.. _server.secret_key: (:ref:`utils/brand.env <make buildenv>`)
``secret_key`` : ``$SEARXNG_SECRET`` ``secret_key`` : ``$SEARXNG_SECRET``
Used for cryptography purpose. Used for cryptography purpose.
``limiter`` : ``$SEARXNG_LIMITER`` .. _limiter:
``limiter`` :
Rate limit the number of request on the instance, block some bots. The Rate limit the number of request on the instance, block some bots. The
:ref:`limiter` requires a :ref:`settings redis` database. :ref:`limiter src` requires a :ref:`settings redis` database.
.. _public_instance:
``public_instance`` : ``$SEARXNG_PUBLIC_INSTANCE``
Setting that allows to enable features specifically for public instances (not
needed for local usage). By set to ``true`` the following features are
activated:
- :py:obj:`searx.botdetection.link_token` in the :ref:`limiter`
.. _image_proxy: .. _image_proxy:
``image_proxy`` : ``$SEARXNG_IMAGE_PROXY`` ``image_proxy`` :
Allow your instance of SearXNG of being able to proxy images. Uses memory space. Allow your instance of SearXNG of being able to proxy images. Uses memory space.
.. _method:
``method`` : ``$SEARXNG_METHOD``
Whether to use ``GET`` or ``POST`` HTTP method when searching.
.. _HTTP headers: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers .. _HTTP headers: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
``default_http_headers`` : ``default_http_headers`` :

View File

@ -19,13 +19,10 @@
default_theme: simple default_theme: simple
theme_args: theme_args:
simple_style: auto simple_style: auto
search_on_category_select: true
hotkeys: default
url_formatting: pretty
.. _static_use_hash: .. _static_use_hash:
``static_use_hash`` : ``$SEARXNG_STATIC_USE_HASH`` ``static_use_hash`` :
Enables `cache busting`_ of static files. Enables `cache busting`_ of static files.
``default_locale`` : ``default_locale`` :
@ -44,7 +41,7 @@
``center_alignment`` : default ``false`` ``center_alignment`` : default ``false``
When enabled, the results are centered instead of being in the left (or RTL) When enabled, the results are centered instead of being in the left (or RTL)
side of the screen. This setting only affects the *desktop layout* side of the screen. This setting only affects the *desktop layout*
(:origin:`min-width: @tablet <client/simple/src/less/definitions.less>`) (:origin:`min-width: @tablet <searx/static/themes/simple/src/less/definitions.less>`)
.. cache_url: .. cache_url:
@ -59,16 +56,7 @@
Name of the theme you want to use by default on your SearXNG instance. Name of the theme you want to use by default on your SearXNG instance.
``theme_args.simple_style``: ``theme_args.simple_style``:
Style of simple theme: ``auto``, ``light``, ``dark``, ``black`` Style of simple theme: ``auto``, ``light``, ``dark``
``results_on_new_tab``: ``results_on_new_tab``:
Open result links in a new tab by default. Open result links in a new tab by default.
``search_on_category_select``:
Perform search immediately if a category selected. Disable to select multiple categories.
``hotkeys``:
Hotkeys to use in the search interface: ``default``, ``vim`` (Vim-like).
``url_formatting``:
Formatting type to use for result URLs: ``pretty``, ``full`` or ``host``.

View File

@ -58,6 +58,9 @@ and then, to name just a few:
- Bot protection has been switched from filtron to SearXNG's :ref:`limiter - Bot protection has been switched from filtron to SearXNG's :ref:`limiter
<limiter>`, this requires a :ref:`Redis <settings redis>` database. <limiter>`, this requires a :ref:`Redis <settings redis>` database.
- The image proxy morty is no longer needed, it has been replaced by the
:ref:`image proxy <image_proxy>` from SearXNG.
- To save bandwidth :ref:`cache busting <static_use_hash>` has been implemented. - To save bandwidth :ref:`cache busting <static_use_hash>` has been implemented.
To get in use, the ``static-expires`` needs to be set in the :ref:`uwsgi To get in use, the ``static-expires`` needs to be set in the :ref:`uwsgi
setup`. setup`.
@ -68,6 +71,12 @@ examples show, this is not always enough, sometimes services have to be set up
or reconfigured and sometimes services that are no longer needed should be or reconfigured and sometimes services that are no longer needed should be
uninstalled. uninstalled.
.. hint::
First of all: SearXNG is installed by the script :ref:`searxng.sh`. If you
have old filtron, morty or searx setup you should consider complete
uninstall/reinstall.
Here you will find a list of changes that affect the infrastructure. Please Here you will find a list of changes that affect the infrastructure. Please
check to what extent it is necessary to update your installations: check to what extent it is necessary to update your installations:
@ -76,6 +85,39 @@ check to what extent it is necessary to update your installations:
file manually. file manually.
remove obsolete services
------------------------
If your searx instance was installed *"Step by step"* or by the *"Installation
scripts"*, you need to undo the installation procedure completely. If you have
morty & filtron installed, it is recommended to uninstall these services also.
In case of scripts, to uninstall use the scripts from the origin you installed
searx from or try::
$ sudo -H ./utils/filtron.sh remove all
$ sudo -H ./utils/morty.sh remove all
$ sudo -H ./utils/searx.sh remove all
.. hint::
If you are migrate from searx take into account that the ``.config.sh`` is no
longer used.
If you upgrade from searx or from before :pull:`1332` has been merged and you
have filtron and/or morty installed, don't forget to remove HTTP sites.
Apache::
$ sudo -H ./utils/filtron.sh apache remove
$ sudo -H ./utils/morty.sh apache remove
nginx::
$ sudo -H ./utils/filtron.sh nginx remove
$ sudo -H ./utils/morty.sh nginx remove
Check after Installation Check after Installation
------------------------ ------------------------
@ -88,6 +130,9 @@ to see if there are some left overs. In this example there exists a *old*
SearXNG checks SearXNG checks
-------------- --------------
ERROR: settings.yml in /etc/searx/ is deprecated, move file to folder /etc/searxng/ ERROR: settings.yml in /etc/searx/ is deprecated, move file to folder /etc/searxng/
INFO: [OK] (old) account 'searx' does not exists
INFO: [OK] (old) account 'filtron' does not exists
INFO: [OK] (old) account 'morty' does not exists
... ...
INFO searx.redisdb : connecting to Redis db=0 path='/usr/local/searxng-redis/run/redis.sock' INFO searx.redisdb : connecting to Redis db=0 path='/usr/local/searxng-redis/run/redis.sock'
INFO searx.redisdb : connected to Redis INFO searx.redisdb : connected to Redis

View File

@ -113,7 +113,7 @@ ${fedora_build}
(${SERVICE_USER})$ command -v python && python --version (${SERVICE_USER})$ command -v python && python --version
$SEARXNG_PYENV/bin/python $SEARXNG_PYENV/bin/python
Python 3.11.10 Python 3.8.1
# update pip's boilerplate .. # update pip's boilerplate ..
pip install -U pip pip install -U pip
@ -123,7 +123,7 @@ ${fedora_build}
# jump to SearXNG's working tree and install SearXNG into virtualenv # jump to SearXNG's working tree and install SearXNG into virtualenv
(${SERVICE_USER})$ cd \"$SEARXNG_SRC\" (${SERVICE_USER})$ cd \"$SEARXNG_SRC\"
(${SERVICE_USER})$ pip install --use-pep517 --no-build-isolation -e . (${SERVICE_USER})$ pip install -e .
.. END manage.sh update_packages .. END manage.sh update_packages

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
import sys, os import sys, os
from pathlib import Path
from pallets_sphinx_themes import ProjectLink from pallets_sphinx_themes import ProjectLink
from searx import get_setting from searx import get_setting
@ -13,6 +13,7 @@ project = 'SearXNG'
copyright = 'SearXNG team' copyright = 'SearXNG team'
author = 'SearXNG team' author = 'SearXNG team'
release, version = VERSION_STRING, VERSION_STRING release, version = VERSION_STRING, VERSION_STRING
SEARXNG_URL = get_setting('server.base_url') or 'https://example.org/searxng' SEARXNG_URL = get_setting('server.base_url') or 'https://example.org/searxng'
ISSUE_URL = get_setting('brand.issue_url') ISSUE_URL = get_setting('brand.issue_url')
DOCS_URL = get_setting('brand.docs_url') DOCS_URL = get_setting('brand.docs_url')
@ -21,9 +22,6 @@ PRIVACYPOLICY_URL = get_setting('general.privacypolicy_url')
CONTACT_URL = get_setting('general.contact_url') CONTACT_URL = get_setting('general.contact_url')
WIKI_URL = get_setting('brand.wiki_url') WIKI_URL = get_setting('brand.wiki_url')
SOURCEDIR = Path(__file__).parent.parent / "searx"
os.environ['SOURCEDIR'] = str(SOURCEDIR)
# hint: sphinx.ext.viewcode won't highlight when 'highlight_language' [1] is set # hint: sphinx.ext.viewcode won't highlight when 'highlight_language' [1] is set
# to string 'none' [2] # to string 'none' [2]
# #
@ -54,7 +52,7 @@ searx.engines.load_engines(searx.settings['engines'])
jinja_contexts = { jinja_contexts = {
'searx': { 'searx': {
'engines': searx.engines.engines, 'engines': searx.engines.engines,
'plugins': searx.plugins.STORAGE, 'plugins': searx.plugins.plugins,
'version': { 'version': {
'node': os.getenv('NODE_MINIMUM_VERSION') 'node': os.getenv('NODE_MINIMUM_VERSION')
}, },
@ -129,9 +127,8 @@ extensions = [
'notfound.extension', # https://github.com/readthedocs/sphinx-notfound-page 'notfound.extension', # https://github.com/readthedocs/sphinx-notfound-page
] ]
# autodoc_typehints = "description"
autodoc_default_options = { autodoc_default_options = {
'member-order': 'bysource', 'member-order': 'groupwise',
} }
myst_enable_extensions = [ myst_enable_extensions = [
@ -143,10 +140,10 @@ suppress_warnings = ['myst.domains']
intersphinx_mapping = { intersphinx_mapping = {
"python": ("https://docs.python.org/3/", None), "python": ("https://docs.python.org/3/", None),
"babel" : ("https://babel.readthedocs.io/en/latest/", None), "babel" : ("https://babel.readthedocs.io/en/latest/", None),
"flask": ("https://flask.palletsprojects.com/en/stable/", None), "flask": ("https://flask.palletsprojects.com/", None),
"flask_babel": ("https://python-babel.github.io/flask-babel/", None), "flask_babel": ("https://python-babel.github.io/flask-babel/", None),
"werkzeug": ("https://werkzeug.palletsprojects.com/en/stable/", None), # "werkzeug": ("https://werkzeug.palletsprojects.com/", None),
"jinja": ("https://jinja.palletsprojects.com/en/stable/", None), "jinja": ("https://jinja.palletsprojects.com/", None),
"linuxdoc" : ("https://return42.github.io/linuxdoc/", None), "linuxdoc" : ("https://return42.github.io/linuxdoc/", None),
"sphinx" : ("https://www.sphinx-doc.org/en/master/", None), "sphinx" : ("https://www.sphinx-doc.org/en/master/", None),
"redis": ('https://redis.readthedocs.io/en/stable/', None), "redis": ('https://redis.readthedocs.io/en/stable/', None),
@ -161,7 +158,7 @@ issues_github_path = "searxng/searxng"
notfound_urls_prefix = '/' notfound_urls_prefix = '/'
sys.path.append(os.path.abspath('_themes')) sys.path.append(os.path.abspath('_themes'))
sys.path.insert(0, os.path.abspath("../")) sys.path.insert(0, os.path.abspath("../utils/"))
html_theme_path = ['_themes'] html_theme_path = ['_themes']
html_theme = "searxng" html_theme = "searxng"
@ -197,7 +194,7 @@ html_sidebars = {
], ],
} }
singlehtml_sidebars = {"index": ["project.html", "localtoc.html"]} singlehtml_sidebars = {"index": ["project.html", "localtoc.html"]}
html_logo = "../client/simple/src/brand/searxng-wordmark.svg" html_logo = "../src/brand/searxng-wordmark.svg"
html_title = "SearXNG Documentation ({})".format(VERSION_STRING) html_title = "SearXNG Documentation ({})".format(VERSION_STRING)
html_show_sourcelink = True html_show_sourcelink = True

View File

@ -1,11 +0,0 @@
.. _builtin answerers:
==================
Built-in Answerers
==================
.. toctree::
:maxdepth: 1
random
statistics

View File

@ -1,7 +0,0 @@
.. _dev answerers:
====================
Answerer Development
====================
.. automodule:: searx.answerers

View File

@ -1,9 +0,0 @@
=========
Answerers
=========
.. toctree::
:maxdepth: 2
development
builtins

View File

@ -1,8 +0,0 @@
.. _answerer.random:
======
Random
======
.. autoclass:: searx.answerers.random.SXNGAnswerer
:members:

View File

@ -1,8 +0,0 @@
.. _answerer.statistics:
==========
Statistics
==========
.. autoclass:: searx.answerers.statistics.SXNGAnswerer
:members:

View File

@ -1,108 +0,0 @@
.. _create commit:
===============================
Git Commits & Change Management
===============================
.. sidebar:: Create good commits!
- `Conventional Commits`_
- `Structural split of changes`_
- `Git Commit Good Practice`_
A commit and its commit message are among the most important information
available to a developer for bug fixing and further development. A commit is a
change and changes have a context (a change request).
In a SCM system (git), the change history is derived from the commit history. A
commit message is therefore part of the documentation for change management and
thus elementary for the traceability of changes.
**What a commit is not**: *A commit to an SCM system is not used to save files!*
A commit should always have a context and the commit message describes what is
to be changed in that context, just as a function description should describe
what the intention and the goal of the function is, a commit message should
describe what the intention and the goal of that commit is.
The commit messages form the history and are the first and therefore most
important information a developer has when he has to research when and why a
change had to be made and how it was made (what the goal was).
Like any text, a commit message should be written for the reader and not from
the perspective of the author.
When scrolling through the history, the first thing one see is the title of the
commit message. Therefore the title should describe the change as briefly and
precisely as possible ... followed by a blank line and then a somewhat detailed
description of the change.
----
The follwing rules should be in mind, when creating a commit:
- **Commit history should be read like a history book.**
- **Commit messages are for the reader not for the author of the commit.**
- **A commit is the atomic code-modification of a change in change management.**
- **Think about which descriptions from your PR might belong in the commit message.**
- **The maximum line length in a commit message is 80 characters.**
----
Choose meaningful commit messages:
.. code::
[type] optional scope: description
[body]
[optional trailers]
``[type]``:
Commits MUST be prefixed with a type .. ``feat``, ``fix``, ``refactor``,
``mod``, ``upd``, ``doc``, ``l10n``, ``build`` ..
``[body]``
`Information in commit messages`_
``[optional trailers]``:
- `Signed-off-by`_: certify that the committer has the rights to submit the
work under the projects license. That the developer has this right is a
prerequisite for a merge. If the `Signed-off-by`_ is not set in the
commit, the contributor enters his `Developer's Certificate of Origin` at
the latest when creating a PR!
- Closes: Link to the bug report or the bug number (e.g. ``Closes: #10``)
- `Co-authored-by`_: email address of the co-author
- Reported-by: email address (if there is no bug report)
- Suggested-by: email address (if there is no bug report)
----
To give examples at hand, here are a few commits. Follow the links to see the
full commit messages:
:patch:`44d941c93`
``[fix] mojeek web engine: don't add empty fmt argument for web searches``
:patch:`feb15e387`
``[fix] brave.news engine: response is HTML and no longer JSON``
:patch:`bdfe1c2a1`
``[mod] engines: migration of the individual cache solutions to EngineCache``
.. _Conventional Commits:
https://www.conventionalcommits.org/
.. _Structural split of changes:
https://wiki.openstack.org/wiki/GitCommitMessages#Structural_split_of_changes
.. _Git Commit Good Practice:
https://wiki.openstack.org/wiki/GitCommitMessages
.. _Information in commit messages:
https://wiki.openstack.org/wiki/GitCommitMessages#Information_in_commit_messages
.. _`Developer's Certificate of Origin`:
https://developercertificate.org/
.. _Signed-off-by:
https://git-scm.com/docs/git-commit#Documentation/git-commit.txt-code--signoffcode
.. _Co-authored-by:
https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors

View File

@ -27,24 +27,23 @@ Privacy-by-design
----------------- -----------------
SearXNG was born out of the need for a **privacy-respecting** search tool which SearXNG was born out of the need for a **privacy-respecting** search tool which
can be extended easily to maximize both its search and its privacy protecting can be extended easily to maximize both, its search and its privacy protecting
capabilities. capabilities.
Some widely used search engine features may work differently, A few widely used features work differently or turned off by default or not
may be turned off by default, or may not be implemented at all in SearXNG implemented at all **as a consequence of privacy-by-design**.
**as a consequence of a privacy-by-design approach**.
Following this approach, features reducing the privacy preserving aspects of SearXNG should be If a feature reduces the privacy preserving aspects of searx, it should be
switched off by default or should not be implemented at all. There are plenty of switched off by default or should not implemented at all. There are plenty of
search engines already providing such features. If a feature reduces search engines already providing such features. If a feature reduces the
SearXNG's efficacy in protecting a user's privacy, the user must be informed about protection of searx, users must be informed about the effect of choosing to
the effect of choosing to enable it. Features that protect privacy but differ from the enable it. Features that protect privacy but differ from the expectations of
expectations of the user should also be carefully explained to them. the user should also be explained.
Also, if you think that something works weird with SearXNG, it might be because Also, if you think that something works weird with searx, it's might be because
the tool you are using is designed in a way that interferes with SearXNG's privacy aspects. of the tool you use is designed in a way to interfere with the privacy respect.
Submitting a bug report to the vendor of the tool that misbehaves might be a good Submitting a bugreport to the vendor of the tool that misbehaves might be a good
feedback for them to reconsider the disrespect to their customers (e.g., ``GET`` vs ``POST`` feedback to reconsider the disrespect to its customers (e.g. ``GET`` vs ``POST``
requests in various browsers). requests in various browsers).
Remember the other prime directive of SearXNG is to be hackable, so if the above Remember the other prime directive of SearXNG is to be hackable, so if the above
@ -56,12 +55,20 @@ Code
==== ====
.. _PEP8: https://www.python.org/dev/peps/pep-0008/ .. _PEP8: https://www.python.org/dev/peps/pep-0008/
.. _Conventional Commits: https://www.conventionalcommits.org/
.. _Git Commit Good Practice: https://wiki.openstack.org/wiki/GitCommitMessages
.. _Structural split of changes: .. _Structural split of changes:
https://wiki.openstack.org/wiki/GitCommitMessages#Structural_split_of_changes https://wiki.openstack.org/wiki/GitCommitMessages#Structural_split_of_changes
.. _gitmoji: https://gitmoji.carloscuesta.me/
.. _Semantic PR: https://github.com/zeke/semantic-pull-requests
.. sidebar:: Create good commits! .. sidebar:: Create good commits!
- :ref:`create commit` - `Structural split of changes`_
- `Conventional Commits`_
- `Git Commit Good Practice`_
- some like to use: gitmoji_
- not yet active: `Semantic PR`_
In order to submit a patch, please follow the steps below: In order to submit a patch, please follow the steps below:
@ -80,7 +87,15 @@ In order to submit a patch, please follow the steps below:
- Add yourself to the :origin:`AUTHORS.rst` file. - Add yourself to the :origin:`AUTHORS.rst` file.
- Choose meaningful commit messages, see :ref:`create commit` - Choose meaningful commit messages, read `Conventional Commits`_
.. code::
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
- Create a pull request. - Create a pull request.
@ -119,7 +134,7 @@ Here is an example which makes a complete rebuild:
.. _make docs.live: .. _make docs.live:
Live build live build
---------- ----------
.. _sphinx-autobuild: .. _sphinx-autobuild:
@ -130,8 +145,8 @@ Live build
It is recommended to assert a complete rebuild before deploying (use It is recommended to assert a complete rebuild before deploying (use
``docs.clean``). ``docs.clean``).
Live build is like WYSIWYG. It's the recommended way to go if you want to edit the documentation. Live build is like WYSIWYG. If you want to edit the documentation, its
The Makefile target ``docs.live`` builds the docs, opens recommended to use. The Makefile target ``docs.live`` builds the docs, opens
URL in your favorite browser and rebuilds every time a reST file has been URL in your favorite browser and rebuilds every time a reST file has been
changed (:ref:`make docs.clean`). changed (:ref:`make docs.clean`).
@ -144,9 +159,9 @@ changed (:ref:`make docs.clean`).
... Start watching changes ... Start watching changes
Live builds are implemented by sphinx-autobuild_. Use environment Live builds are implemented by sphinx-autobuild_. Use environment
``$(SPHINXOPTS)`` to pass arguments to the sphinx-autobuild_ command. You can ``$(SPHINXOPTS)`` to pass arguments to the sphinx-autobuild_ command. Except
pass any argument except for the ``--host`` option (which is always set to ``0.0.0.0``). option ``--host`` (which is always set to ``0.0.0.0``) you can pass any
E.g., to find and use a free port, use: argument. E.g to find and use a free port, use:
.. code:: sh .. code:: sh

View File

@ -14,7 +14,7 @@ Engine Overview
.. sidebar:: Further reading .. .. sidebar:: Further reading ..
- :ref:`configured engines` - :ref:`configured engines`
- :ref:`settings engines` - :ref:`settings engine`
SearXNG is a metasearch-engine_, so it uses different search engines to provide SearXNG is a metasearch-engine_, so it uses different search engines to provide
better results. better results.
@ -63,7 +63,7 @@ Engine File
Engine ``settings.yml`` Engine ``settings.yml``
----------------------- -----------------------
For a more detailed description, see :ref:`settings engines` in the :ref:`settings.yml`. For a more detailed description, see :ref:`settings engine` in the :ref:`settings.yml`.
.. table:: Common options in the engine setup (``settings.yml``) .. table:: Common options in the engine setup (``settings.yml``)
:width: 100% :width: 100%
@ -87,8 +87,8 @@ For a more detailed description, see :ref:`settings engines` in the :ref:`setti
Overrides Overrides
--------- ---------
A few of the options have default values in the namespace of the engine's python A few of the options have default values in the namespace of engine's python
module, but are often overwritten by the settings. If ``None`` is assigned to an modul, but are often overwritten by the settings. If ``None`` is assigned to an
option in the engine file, it has to be redefined in the settings, otherwise option in the engine file, it has to be redefined in the settings, otherwise
SearXNG will not start with that engine (global names with a leading underline can SearXNG will not start with that engine (global names with a leading underline can
be ``None``). be ``None``).
@ -237,18 +237,232 @@ following parameters can be used to specify a search request:
=================== =========== ========================================================================== =================== =========== ==========================================================================
Making a Response .. _engine results:
================= .. _engine media types:
In the ``response`` function of the engine, the HTTP response (``resp``) is Result Types (``template``)
parsed and a list of results is returned. ===========================
A engine can append result-items of different media-types and different Each result item of an engine can be of different media-types. Currently the
result-types to the result list. The list of the result items is render to HTML following media-types are supported. To set another media-type as
by templates. For more details read section: :ref:`template default`, the parameter ``template`` must be set to the desired
type.
- :ref:`simple theme templates` .. _template default:
- :ref:`result types`
``default``
-----------
.. table:: Parameter of the **default** media type:
:width: 100%
========================= =====================================================
result-parameter information
========================= =====================================================
url string, url of the result
title string, title of the result
content string, general result-text
publishedDate :py:class:`datetime.datetime`, time of publish
========================= =====================================================
.. _template images:
``images``
----------
.. table:: Parameter of the **images** media type:
:width: 100%
========================= =====================================================
result-parameter information
------------------------- -----------------------------------------------------
template is set to ``images.html``
========================= =====================================================
url string, url to the result site
title string, title of the result *(partly implemented)*
content *(partly implemented)*
publishedDate :py:class:`datetime.datetime`,
time of publish *(partly implemented)*
img\_src string, url to the result image
thumbnail\_src string, url to a small-preview image
========================= =====================================================
.. _template videos:
``videos``
----------
.. table:: Parameter of the **videos** media type:
:width: 100%
========================= =====================================================
result-parameter information
------------------------- -----------------------------------------------------
template is set to ``videos.html``
========================= =====================================================
url string, url of the result
title string, title of the result
content *(not implemented yet)*
publishedDate :py:class:`datetime.datetime`, time of publish
thumbnail string, url to a small-preview image
========================= =====================================================
.. _template torrent:
``torrent``
-----------
.. _magnetlink: https://en.wikipedia.org/wiki/Magnet_URI_scheme
.. table:: Parameter of the **torrent** media type:
:width: 100%
========================= =====================================================
result-parameter information
------------------------- -----------------------------------------------------
template is set to ``torrent.html``
========================= =====================================================
url string, url of the result
title string, title of the result
content string, general result-text
publishedDate :py:class:`datetime.datetime`,
time of publish *(not implemented yet)*
seed int, number of seeder
leech int, number of leecher
filesize int, size of file in bytes
files int, number of files
magnetlink string, magnetlink_ of the result
torrentfile string, torrentfile of the result
========================= =====================================================
.. _template map:
``map``
-------
.. table:: Parameter of the **map** media type:
:width: 100%
========================= =====================================================
result-parameter information
------------------------- -----------------------------------------------------
template is set to ``map.html``
========================= =====================================================
url string, url of the result
title string, title of the result
content string, general result-text
publishedDate :py:class:`datetime.datetime`, time of publish
latitude latitude of result (in decimal format)
longitude longitude of result (in decimal format)
boundingbox boundingbox of result (array of 4. values
``[lat-min, lat-max, lon-min, lon-max]``)
geojson geojson of result (https://geojson.org/)
osm.type type of osm-object (if OSM-Result)
osm.id id of osm-object (if OSM-Result)
address.name name of object
address.road street name of object
address.house_number house number of object
address.locality city, place of object
address.postcode postcode of object
address.country country of object
========================= =====================================================
.. _template paper:
``paper``
---------
.. _BibTeX format: https://www.bibtex.com/g/bibtex-format/
.. _BibTeX field types: https://en.wikipedia.org/wiki/BibTeX#Field_types
.. list-table:: Parameter of the **paper** media type /
see `BibTeX field types`_ and `BibTeX format`_
:header-rows: 2
:width: 100%
* - result-parameter
- Python type
- information
* - template
- :py:class:`str`
- is set to ``paper.html``
* - title
- :py:class:`str`
- title of the result
* - content
- :py:class:`str`
- abstract
* - comments
- :py:class:`str`
- free text display in italic below the content
* - tags
- :py:class:`List <list>`\ [\ :py:class:`str`\ ]
- free tag list
* - publishedDate
- :py:class:`datetime <datetime.datetime>`
- last publication date
* - type
- :py:class:`str`
- short description of medium type, e.g. *book*, *pdf* or *html* ...
* - authors
- :py:class:`List <list>`\ [\ :py:class:`str`\ ]
- list of authors of the work (authors with a "s")
* - editor
- :py:class:`str`
- list of editors of a book
* - publisher
- :py:class:`str`
- name of the publisher
* - journal
- :py:class:`str`
- name of the journal or magazine the article was
published in
* - volume
- :py:class:`str`
- volume number
* - pages
- :py:class:`str`
- page range where the article is
* - number
- :py:class:`str`
- number of the report or the issue number for a journal article
* - doi
- :py:class:`str`
- DOI number (like ``10.1038/d41586-018-07848-2``)
* - issn
- :py:class:`List <list>`\ [\ :py:class:`str`\ ]
- ISSN number like ``1476-4687``
* - isbn
- :py:class:`List <list>`\ [\ :py:class:`str`\ ]
- ISBN number like ``9780201896831``
* - pdf_url
- :py:class:`str`
- URL to the full article, the PDF version
* - html_url
- :py:class:`str`
- URL to full article, HTML version

View File

@ -4,13 +4,19 @@
Engine Library Engine Library
============== ==============
.. contents::
:depth: 2
:local:
:backlinks: entry
.. automodule:: searx.enginelib .. automodule:: searx.enginelib
:members: :members:
.. _searx.enginelib.traits: .. _searx.enginelib.traits:
Engine traits Engine traits
============= =============
.. automodule:: searx.enginelib.traits .. automodule:: searx.enginelib.traits
:members: :members:

View File

@ -19,14 +19,6 @@ Engine Implementations
engine_overview engine_overview
ResultList and engines
======================
.. autoclass:: searx.result_types.ResultList
.. autoclass:: searx.result_types.EngineResults
Engine Types Engine Types
============ ============
@ -53,7 +45,6 @@ Online Engines
demo/demo_online demo/demo_online
xpath xpath
mediawiki mediawiki
json_engine
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1
@ -102,7 +93,7 @@ Online Currency
- :py:obj:`processors.online_currency <searx.search.processors.online_currency>` - :py:obj:`processors.online_currency <searx.search.processors.online_currency>`
*no engine of this type is documented yet / coming soon* *no engine of this type is documented yet / comming soon*
.. _online dictionary: .. _online dictionary:
@ -113,4 +104,4 @@ Online Dictionary
- :py:obj:`processors.online_dictionary <searx.search.processors.online_dictionary>` - :py:obj:`processors.online_dictionary <searx.search.processors.online_dictionary>`
*no engine of this type is documented yet / coming soon* *no engine of this type is documented yet / comming soon*

View File

@ -1,13 +0,0 @@
.. _json_engine engine:
============
JSON Engine
============
.. contents::
:depth: 2
:local:
:backlinks: entry
.. automodule:: searx.engines.json_engine
:members:

View File

@ -25,7 +25,7 @@ Relational Database Management System (RDBMS) are supported:
- :ref:`engine sqlite` - :ref:`engine sqlite`
- :ref:`engine postgresql` - :ref:`engine postgresql`
- :ref:`engine mysql_server` & :ref:`engine mariadb_server` - :ref:`engine mysql_server`
All of the engines above are just commented out in the :origin:`settings.yml All of the engines above are just commented out in the :origin:`settings.yml
<searx/settings.yml>`, as you have to set the required attributes for the <searx/settings.yml>`, as you have to set the required attributes for the
@ -119,16 +119,3 @@ MySQL
.. automodule:: searx.engines.mysql_server .. automodule:: searx.engines.mysql_server
:members: :members:
.. _engine mariadb_server:
MariaDB
--------
.. sidebar:: info
- :origin:`mariadb_server.py <searx/engines/mariadb_server.py>`
- ``pip install`` :pypi:`mariadb <mariadb>`
.. automodule:: searx.engines.mariadb_server
:members:

View File

@ -29,7 +29,7 @@ Programming Interface
parameter. This function can be omitted, if there is no need to setup anything parameter. This function can be omitted, if there is no need to setup anything
in advance. in advance.
:py:func:`search(query, params) <searx.engines.demo_offline.search>` :py:func:`search(query, params) <searx.engines.demo_offline.searc>`
Each offline engine has a function named ``search``. This function is Each offline engine has a function named ``search``. This function is
responsible to perform a search and return the results in a presentable responsible to perform a search and return the results in a presentable
format. (Where *presentable* means presentable by the selected result format. (Where *presentable* means presentable by the selected result

View File

@ -1,13 +0,0 @@
.. _adobe stock engine:
===========
Adobe Stock
===========
.. contents:: Contents
:depth: 2
:local:
:backlinks: entry
.. automodule:: searx.engines.adobe_stock
:members:

View File

@ -1,13 +0,0 @@
.. _alpinelinux engine:
=====================
Alpine Linux Packages
=====================
.. contents::
:depth: 2
:local:
:backlinks: entry
.. automodule:: searx.engines.alpinelinux
:members:

View File

@ -1,13 +0,0 @@
.. _bpb engine:
===
Bpb
===
.. contents:: Contents
:depth: 2
:local:
:backlinks: entry
.. automodule:: searx.engines.bpb
:members:

View File

@ -1,8 +0,0 @@
.. _chinaso engine:
=======
ChinaSo
=======
.. automodule:: searx.engines.chinaso
:members:

View File

@ -1,13 +0,0 @@
.. _core engine:
====
CORE
====
.. contents::
:depth: 2
:local:
:backlinks: entry
.. automodule:: searx.engines.core
:members:

View File

@ -1,8 +0,0 @@
.. _discourse engine:
================
Discourse Forums
================
.. automodule:: searx.engines.discourse
:members:

View File

@ -12,7 +12,7 @@ DuckDuckGo Engines
.. automodule:: searx.engines.duckduckgo .. automodule:: searx.engines.duckduckgo
:members: :members:
.. automodule:: searx.engines.duckduckgo_extra .. automodule:: searx.engines.duckduckgo_images
:members: :members:
.. automodule:: searx.engines.duckduckgo_definitions .. automodule:: searx.engines.duckduckgo_definitions

View File

@ -1,8 +0,0 @@
.. _gitea geizhals:
========
Geizhals
========
.. automodule:: searx.engines.geizhals
:members:

View File

@ -1,8 +0,0 @@
.. _gitea engine:
=====
Gitea
=====
.. automodule:: searx.engines.gitea
:members:

View File

@ -1,8 +0,0 @@
.. _gitlab engine:
======
GitLab
======
.. automodule:: searx.engines.gitlab
:members:

View File

@ -1,8 +0,0 @@
.. _huggingface engine:
============
Hugging Face
============
.. automodule:: searx.engines.huggingface
:members:

View File

@ -1,13 +0,0 @@
.. _mastodon engine:
========
Mastodon
========
.. contents:: Contents
:depth: 2
:local:
:backlinks: entry
.. automodule:: searx.engines.mastodon
:members:

View File

@ -1,13 +0,0 @@
.. _moviepilot engine:
==========
Moviepilot
==========
.. contents:: Contents
:depth: 2
:local:
:backlinks: entry
.. automodule:: searx.engines.moviepilot
:members:

View File

@ -1,13 +0,0 @@
.. _mrs engine:
=========================
Matrix Rooms Search (MRS)
=========================
.. contents:: Contents
:depth: 2
:local:
:backlinks: entry
.. automodule:: searx.engines.mrs
:members:

View File

@ -1,8 +0,0 @@
.. _voidlinux mullvad_leta:
============
Mullvad-Leta
============
.. automodule:: searx.engines.mullvad_leta
:members:

View File

@ -1,13 +0,0 @@
.. _engine presearch:
================
Presearch Engine
================
.. contents::
:depth: 2
:local:
:backlinks: entry
.. automodule:: searx.engines.presearch
:members:

View File

@ -1,13 +0,0 @@
.. _qwant engine:
=====
Qwant
=====
.. contents:: Contents
:depth: 2
:local:
:backlinks: entry
.. automodule:: searx.engines.qwant
:members:

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