forked from Icycoide/searxng
Compare commits
1 commit
master
...
dependabot
Author | SHA1 | Date | |
---|---|---|---|
|
45c18a4c78 |
569 changed files with 24437 additions and 63389 deletions
|
@ -3,8 +3,7 @@
|
|||
"dockerfile": "Dockerfile"
|
||||
},
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/github-cli": {},
|
||||
"ghcr.io/devcontainers/features/docker-in-docker": {}
|
||||
"ghcr.io/devcontainers/features/github-cli": {}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
|
|
|
@ -16,17 +16,11 @@ max_line_length = 119
|
|||
[*.html]
|
||||
indent_size = 4
|
||||
|
||||
[*.css]
|
||||
indent_size = 2
|
||||
|
||||
[*.less]
|
||||
indent_size = 2
|
||||
|
||||
[*.js]
|
||||
indent_size = 2
|
||||
|
||||
[*.json]
|
||||
indent_size = 2
|
||||
indent_size = 4
|
||||
insert_final_newline = ignore
|
||||
|
||||
# Minified JavaScript files shouldn't be changed
|
||||
|
|
34
.github/dependabot.yml
vendored
34
.github/dependabot.yml
vendored
|
@ -10,43 +10,13 @@ updates:
|
|||
target-branch: "master"
|
||||
commit-message:
|
||||
prefix: "[upd] pypi:"
|
||||
groups:
|
||||
minor:
|
||||
applies-to: version-updates
|
||||
update-types:
|
||||
- "minor"
|
||||
- "patch"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/client/simple"
|
||||
directory: "/searx/static/themes/simple"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "friday"
|
||||
open-pull-requests-limit: 5
|
||||
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:"
|
||||
prefix: "[upd] npm:"
|
||||
|
|
57
.github/workflows/checker.yml
vendored
57
.github/workflows/checker.yml
vendored
|
@ -1,46 +1,31 @@
|
|||
---
|
||||
name: Checker
|
||||
|
||||
# yamllint disable-line rule:truthy
|
||||
on:
|
||||
workflow_dispatch:
|
||||
name: "Checker"
|
||||
on: # yamllint disable-line rule:truthy
|
||||
schedule:
|
||||
- cron: "0 4 * * 5"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
PYTHON_VERSION: "3.13"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
search:
|
||||
name: Search
|
||||
runs-on: ubuntu-24.04-arm
|
||||
checker:
|
||||
name: Checker
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Ubuntu packages
|
||||
run: |
|
||||
sudo ./utils/searxng.sh install packages
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "${{ env.PYTHON_VERSION }}"
|
||||
python-version: '3.13'
|
||||
architecture: 'x64'
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: "false"
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
make V=1 install
|
||||
|
||||
- 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
|
||||
- name: Checker
|
||||
run: |
|
||||
make search.checker
|
||||
|
|
36
.github/workflows/cleanup.yml
vendored
36
.github/workflows/cleanup.yml
vendored
|
@ -1,36 +0,0 @@
|
|||
---
|
||||
name: Cleanup
|
||||
|
||||
# yamllint disable-line rule:truthy
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "4 4 * * *"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
container-cache:
|
||||
# FIXME: On forks it fails with "Failed to fetch packages: missing field `id` at line 1 column 141"
|
||||
if: github.repository_owner == 'searxng' || github.event_name == 'workflow_dispatch'
|
||||
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 base"
|
||||
image-tags: "!searxng*"
|
||||
cut-off: "1d"
|
||||
keep-n-most-recent: "100"
|
252
.github/workflows/container.yml
vendored
252
.github/workflows/container.yml
vendored
|
@ -1,252 +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-base:
|
||||
if: |
|
||||
(github.repository_owner == 'searxng' && github.event.workflow_run.conclusion == 'success')
|
||||
|| github.event_name == 'workflow_dispatch'
|
||||
name: Build base
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
# Organization GHCR
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- if: github.repository_owner == 'searxng'
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: "false"
|
||||
|
||||
- if: github.repository_owner == 'searxng'
|
||||
name: Get date
|
||||
id: date
|
||||
run: echo "date=$(date +'%Y%m%d')" >>$GITHUB_OUTPUT
|
||||
|
||||
- if: github.repository_owner == 'searxng'
|
||||
name: Check cache apko
|
||||
id: cache-apko
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
# yamllint disable-line rule:line-length
|
||||
key: "apko-${{ steps.date.outputs.date }}-${{ hashFiles('./container/base.yml', './container/base-builder.yml') }}"
|
||||
path: "/tmp/.apko/"
|
||||
lookup-only: true
|
||||
|
||||
- if: github.repository_owner == 'searxng' && steps.cache-apko.outputs.cache-hit != 'true'
|
||||
name: Setup cache apko
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
# yamllint disable-line rule:line-length
|
||||
key: "apko-${{ steps.date.outputs.date }}-${{ hashFiles('./container/base.yml', './container/base-builder.yml') }}"
|
||||
restore-keys: "apko-${{ steps.date.outputs.date }}-"
|
||||
path: "/tmp/.apko/"
|
||||
|
||||
- if: github.repository_owner == 'searxng' && steps.cache-apko.outputs.cache-hit != 'true'
|
||||
name: Setup apko
|
||||
run: |
|
||||
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
|
||||
brew install apko
|
||||
|
||||
- if: github.repository_owner == 'searxng' && steps.cache-apko.outputs.cache-hit != 'true'
|
||||
name: Login to GHCR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: "ghcr.io"
|
||||
username: "${{ github.repository_owner }}"
|
||||
password: "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
- if: github.repository_owner == 'searxng' && steps.cache-apko.outputs.cache-hit != 'true'
|
||||
name: Build
|
||||
run: |
|
||||
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
|
||||
|
||||
apko publish ./container/base.yml ghcr.io/${{ github.repository_owner }}/base:searxng \
|
||||
--cache-dir=/tmp/.apko/ \
|
||||
--sbom=false \
|
||||
--vcs=false \
|
||||
--log-level=debug
|
||||
|
||||
apko publish ./container/base-builder.yml ghcr.io/${{ github.repository_owner }}/base:searxng-builder \
|
||||
--cache-dir=/tmp/.apko/ \
|
||||
--sbom=false \
|
||||
--vcs=false \
|
||||
--log-level=debug
|
||||
|
||||
build:
|
||||
if: github.repository_owner == 'searxng' || github.event_name == 'workflow_dispatch'
|
||||
name: Build (${{ matrix.arch }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: build-base
|
||||
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
|
88
.github/workflows/data-update.yml
vendored
88
.github/workflows/data-update.yml
vendored
|
@ -1,27 +1,14 @@
|
|||
---
|
||||
name: Update searx.data
|
||||
|
||||
# yamllint disable-line rule:truthy
|
||||
on:
|
||||
workflow_dispatch:
|
||||
name: "Update searx.data"
|
||||
on: # yamllint disable-line rule:truthy
|
||||
schedule:
|
||||
- cron: "59 23 28 * *"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
PYTHON_VERSION: "3.13"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
data:
|
||||
if: github.repository_owner == 'searxng'
|
||||
name: ${{ matrix.fetch }}
|
||||
runs-on: ubuntu-24.04-arm
|
||||
updateData:
|
||||
name: Update data - ${{ matrix.fetch }}
|
||||
runs-on: ubuntu-24.04
|
||||
if: ${{ github.repository_owner == 'searxng'}}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
@ -33,53 +20,48 @@ jobs:
|
|||
- update_engine_traits.py
|
||||
- update_wikidata_units.py
|
||||
- update_engine_descriptions.py
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Ubuntu packages
|
||||
run: |
|
||||
sudo ./utils/searxng.sh install packages
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "${{ env.PYTHON_VERSION }}"
|
||||
python-version: '3.12'
|
||||
architecture: 'x64'
|
||||
|
||||
- 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: Install Python dependencies
|
||||
run: |
|
||||
make V=1 install
|
||||
|
||||
- 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
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
author: "searxng-bot <searxng-bot@users.noreply.github.com>"
|
||||
committer: "searxng-bot <searxng-bot@users.noreply.github.com>"
|
||||
title: "[data] update searx.data - ${{ matrix.fetch }}"
|
||||
commit-message: "[data] update searx.data - ${{ matrix.fetch }}"
|
||||
branch: "update_data_${{ matrix.fetch }}"
|
||||
delete-branch: "true"
|
||||
draft: "false"
|
||||
signoff: "false"
|
||||
commit-message: '[data] update searx.data - ${{ matrix.fetch }}'
|
||||
committer: searxng-bot <noreply@github.com>
|
||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||
signoff: false
|
||||
branch: update_data_${{ matrix.fetch }}
|
||||
delete-branch: true
|
||||
draft: false
|
||||
title: '[data] update searx.data - ${{ matrix.fetch }}'
|
||||
body: |
|
||||
[data] update searx.data - ${{ matrix.fetch }}
|
||||
update searx.data - ${{ matrix.fetch }}
|
||||
labels: |
|
||||
data
|
||||
|
||||
- name: Display information
|
||||
- name: Check outputs
|
||||
run: |
|
||||
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
|
||||
echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}"
|
||||
|
|
66
.github/workflows/documentation.yml
vendored
66
.github/workflows/documentation.yml
vendored
|
@ -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"
|
229
.github/workflows/integration.yml
vendored
229
.github/workflows/integration.yml
vendored
|
@ -1,96 +1,205 @@
|
|||
---
|
||||
name: Integration
|
||||
|
||||
# yamllint disable-line rule:truthy
|
||||
on:
|
||||
on: # yamllint disable-line rule:truthy
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
branches: ["master"]
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref_name }}
|
||||
cancel-in-progress: false
|
||||
branches: ["master"]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
PYTHON_VERSION: "3.13"
|
||||
|
||||
jobs:
|
||||
test:
|
||||
python:
|
||||
name: Python ${{ matrix.python-version }}
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version:
|
||||
- "3.9"
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
- "3.12"
|
||||
- "3.13"
|
||||
|
||||
os: [ubuntu-20.04]
|
||||
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Ubuntu packages
|
||||
run: |
|
||||
sudo ./utils/searxng.sh install packages
|
||||
sudo apt install firefox
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "${{ matrix.python-version }}"
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: "false"
|
||||
|
||||
- name: Setup cache Python
|
||||
python-version: ${{ matrix.python-version }}
|
||||
architecture: 'x64'
|
||||
- name: Cache Python dependencies
|
||||
id: cache-python
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: "python-${{ matrix.python-version }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
|
||||
restore-keys: "python-${{ matrix.python-version }}-${{ runner.arch }}-"
|
||||
path: "./local/"
|
||||
|
||||
- name: Setup venv
|
||||
run: make V=1 install
|
||||
|
||||
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
|
||||
|
||||
theme:
|
||||
name: Theme
|
||||
runs-on: ubuntu-24.04-arm
|
||||
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@v5
|
||||
with:
|
||||
python-version: "${{ env.PYTHON_VERSION }}"
|
||||
python-version: '3.12'
|
||||
architecture: 'x64'
|
||||
- name: Cache Python dependencies
|
||||
id: cache-python
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
./local
|
||||
./.nvm
|
||||
./node_modules
|
||||
key: python-ubuntu-20.04-3.12-${{ 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:
|
||||
persist-credentials: "false"
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
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@v5
|
||||
with:
|
||||
node-version-file: "./.nvmrc"
|
||||
|
||||
- name: Setup cache Node.js
|
||||
python-version: '3.12'
|
||||
architecture: 'x64'
|
||||
- name: Cache Python dependencies
|
||||
id: cache-python
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: "nodejs-${{ runner.arch }}-${{ hashFiles('./.nvmrc', './package.json') }}"
|
||||
path: "./client/simple/node_modules/"
|
||||
path: |
|
||||
./local
|
||||
./.nvm
|
||||
./node_modules
|
||||
key: python-ubuntu-20.04-3.12-${{ 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: '[doc] build from commit ${{ github.sha }}'
|
||||
|
||||
- name: Setup cache Python
|
||||
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@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
architecture: 'x64'
|
||||
- name: Cache Python dependencies
|
||||
id: 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/"
|
||||
path: |
|
||||
./local
|
||||
./.nvm
|
||||
./node_modules
|
||||
key: python-ubuntu-20.04-3.12-${{ 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: |
|
||||
make V=1 weblate.push.translations
|
||||
|
||||
- name: Setup venv
|
||||
run: make V=1 install
|
||||
|
||||
- name: Build
|
||||
run: make themes.all
|
||||
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
|
||||
if: env.DOCKERHUB_USERNAME != null
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# make sure "make docker.push" can get the git history
|
||||
fetch-depth: '0'
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
architecture: 'x64'
|
||||
- name: Cache Python dependencies
|
||||
id: cache-python
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
./local
|
||||
./.nvm
|
||||
./node_modules
|
||||
key: python-ubuntu-20.04-3.12-${{ 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:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push
|
||||
if: env.DOCKERHUB_USERNAME != null
|
||||
run: make -e GIT_URL=$(git remote get-url origin) docker.buildx
|
||||
|
|
138
.github/workflows/l10n.yml
vendored
138
.github/workflows/l10n.yml
vendored
|
@ -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 }}"
|
50
.github/workflows/security.yml
vendored
50
.github/workflows/security.yml
vendored
|
@ -1,44 +1,28 @@
|
|||
---
|
||||
name: Security
|
||||
|
||||
# yamllint disable-line rule:truthy
|
||||
on:
|
||||
workflow_dispatch:
|
||||
name: "Security checks"
|
||||
on: # yamllint disable-line rule:truthy
|
||||
schedule:
|
||||
- cron: "42 05 * * *"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
container:
|
||||
if: github.repository_owner == 'searxng'
|
||||
name: Container
|
||||
runs-on: ubuntu-24.04-arm
|
||||
permissions:
|
||||
security-events: write
|
||||
|
||||
dockers:
|
||||
name: Trivy ${{ matrix.image }}
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: "false"
|
||||
|
||||
- name: Run Trivy scanner
|
||||
uses: aquasecurity/trivy-action@0.30.0
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
image-ref: "ghcr.io/searxng/searxng:latest"
|
||||
vuln-type: "os,library"
|
||||
severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"
|
||||
ignore-unfixed: "false"
|
||||
format: "sarif"
|
||||
output: "./trivy-results.sarif"
|
||||
image-ref: 'searxng/searxng:latest'
|
||||
ignore-unfixed: false
|
||||
vuln-type: 'os,library'
|
||||
severity: 'UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL'
|
||||
format: 'sarif'
|
||||
output: 'trivy-results.sarif'
|
||||
|
||||
- name: Upload SARIFs
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: "./trivy-results.sarif"
|
||||
sarif_file: 'trivy-results.sarif'
|
||||
|
|
59
.github/workflows/translations-update.yml
vendored
Normal file
59
.github/workflows/translations-update.yml
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
name: "Update translations"
|
||||
on: # yamllint disable-line rule:truthy
|
||||
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@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
architecture: 'x64'
|
||||
- name: Cache Python dependencies
|
||||
id: cache-python
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
./local
|
||||
./.nvm
|
||||
./node_modules
|
||||
key: python-ubuntu-20.04-3.12-${{ 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: '[l10n] update translations from Weblate'
|
||||
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: '[l10n] update translations from Weblate'
|
||||
body: |
|
||||
update translations from Weblate
|
||||
labels: |
|
||||
translation
|
2
.nvmrc
2
.nvmrc
|
@ -1 +1 @@
|
|||
v23.5
|
||||
v20.10
|
|
@ -1,4 +1,2 @@
|
|||
nodejs 23.5.0
|
||||
python 3.13.1
|
||||
shellcheck 0.10.0
|
||||
sqlite 3.47.2
|
||||
python 3.12.0
|
||||
shellcheck 0.9.0
|
||||
|
|
|
@ -174,6 +174,3 @@ features or generally made searx better:
|
|||
- @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>`
|
||||
|
|
89
Dockerfile
Normal file
89
Dockerfile
Normal file
|
@ -0,0 +1,89 @@
|
|||
FROM alpine:3.20
|
||||
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 \
|
||||
UWSGI_WORKERS=%k \
|
||||
UWSGI_THREADS=4
|
||||
|
||||
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 \
|
||||
python3 \
|
||||
py3-pip \
|
||||
libxml2 \
|
||||
libxslt \
|
||||
openssl \
|
||||
tini \
|
||||
uwsgi \
|
||||
uwsgi-python3 \
|
||||
brotli \
|
||||
&& pip3 install --break-system-packages --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"
|
25
Makefile
25
Makefile
|
@ -50,11 +50,11 @@ search.checker.%: install
|
|||
$(Q)./manage pyenv.cmd searxng-checker -v "$(subst _, ,$(patsubst search.checker.%,%,$@))"
|
||||
|
||||
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
|
||||
test: test.yamllint test.black test.types.dev test.pylint test.unit test.robot test.rst test.shell
|
||||
ci.test: test.yamllint test.black test.pyright test.pylint test.unit test.robot test.rst test.pybabel
|
||||
test: test.yamllint test.black test.pyright test.pylint test.unit test.robot test.rst test.shell
|
||||
test.shell:
|
||||
$(Q)shellcheck -x -s dash \
|
||||
container/entrypoint.sh
|
||||
dockerfiles/docker-entrypoint.sh
|
||||
$(Q)shellcheck -x -s bash \
|
||||
utils/brand.sh \
|
||||
$(MTOOLS) \
|
||||
|
@ -65,25 +65,26 @@ test.shell:
|
|||
utils/lib_redis.sh \
|
||||
utils/searxng.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"
|
||||
|
||||
|
||||
# wrap ./manage script
|
||||
|
||||
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 data.locales
|
||||
MANAGE += docs.html docs.live docs.gh-pages docs.prebuild docs.clean
|
||||
MANAGE += podman.build
|
||||
MANAGE += docker.build docker.buildx
|
||||
MANAGE += container.build container.test container.push
|
||||
MANAGE += docker.build docker.push docker.buildx
|
||||
MANAGE += gecko.driver
|
||||
MANAGE += node.env node.env.dev node.clean
|
||||
MANAGE += py.build py.clean
|
||||
MANAGE += pyenv pyenv.install pyenv.uninstall
|
||||
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 += themes.all themes.fix themes.test
|
||||
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.simple themes.simple.test pygments.less
|
||||
MANAGE += static.build.commit static.build.drop static.build.restore
|
||||
MANAGE += nvm.install nvm.clean nvm.status nvm.nodejs
|
||||
|
||||
|
@ -94,8 +95,8 @@ $(MANAGE):
|
|||
|
||||
# short hands of selected targets
|
||||
|
||||
PHONY += docs container themes
|
||||
PHONY += docs docker themes
|
||||
|
||||
docs: docs.html
|
||||
container: container.build
|
||||
docker: docker.build
|
||||
themes: themes.all
|
||||
|
|
|
@ -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/
|
||||
:alt: SearXNG
|
||||
:width: 100%
|
||||
|
@ -10,8 +10,6 @@
|
|||
|
||||
----
|
||||
|
||||
Fork of SearXNG. The globe icon for empty_favicon.svg in searx/static/themes/simple/img/ belongs to the Noto Emojis font by Google
|
||||
|
||||
Privacy-respecting, hackable `metasearch engine`_
|
||||
|
||||
Searx.space_ lists ready-to-use running instances.
|
||||
|
@ -36,7 +34,7 @@ A user_, admin_ and developer_ handbook is available on the homepage_.
|
|||
.. _homepage: https://docs.searxng.org/
|
||||
.. _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/
|
||||
:width: 5%
|
||||
|
||||
|
|
3
client/simple/.gitignore
vendored
3
client/simple/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
|||
dist
|
||||
node_modules
|
||||
.stylelintcache
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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],
|
||||
},
|
||||
},
|
||||
|
||||
];
|
7398
client/simple/package-lock.json
generated
7398
client/simple/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,38 +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.27.0",
|
||||
"copy-webpack-plugin": "^13.0.0",
|
||||
"css-loader": "^7.1.2",
|
||||
"edge.js": "^6.2.1",
|
||||
"eslint": "^9.27.0",
|
||||
"filemanager-webpack-plugin": "^8.0.0",
|
||||
"globals": "^16.2.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.2",
|
||||
"style-loader": "^4.0.0",
|
||||
"stylelint": "^16.20.0",
|
||||
"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": "^3.0.0",
|
||||
"vite-plugin-stylelint": "^6.0.0",
|
||||
"webpack": "^5.99.9",
|
||||
"webpack-cli": "^6.0.1"
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -1,199 +0,0 @@
|
|||
/* SPDX-License-Identifier: AGPL-3.0-or-later */
|
||||
/* exported AutoComplete */
|
||||
|
||||
(function (w, d, searxng) {
|
||||
'use strict';
|
||||
|
||||
var qinput_id = "q", qinput;
|
||||
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 50em)").matches;
|
||||
const isResultsPage = document.querySelector("main").id == "main_results";
|
||||
|
||||
function submitIfQuery () {
|
||||
if (qinput.value.length > 0) {
|
||||
var search = document.getElementById('search');
|
||||
setTimeout(search.submit.bind(search), 0);
|
||||
}
|
||||
}
|
||||
|
||||
function createClearButton (qinput) {
|
||||
var cs = document.getElementById('clear_search');
|
||||
var updateClearButton = function () {
|
||||
if (qinput.value.length === 0) {
|
||||
cs.classList.add("empty");
|
||||
} else {
|
||||
cs.classList.remove("empty");
|
||||
}
|
||||
};
|
||||
|
||||
// update status, event listener
|
||||
updateClearButton();
|
||||
cs.addEventListener('click', function (ev) {
|
||||
qinput.value = '';
|
||||
qinput.focus();
|
||||
updateClearButton();
|
||||
ev.preventDefault();
|
||||
});
|
||||
qinput.addEventListener('input', updateClearButton, false);
|
||||
}
|
||||
|
||||
const fetchResults = async (query) => {
|
||||
let request;
|
||||
if (searxng.settings.method === 'GET') {
|
||||
const reqParams = new URLSearchParams();
|
||||
reqParams.append("q", query);
|
||||
request = fetch("./autocompleter?" + reqParams.toString());
|
||||
} else {
|
||||
const formData = new FormData();
|
||||
formData.append("q", query);
|
||||
request = fetch("./autocompleter", {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
});
|
||||
}
|
||||
|
||||
request.then(async function (response) {
|
||||
const results = await response.json();
|
||||
|
||||
if (!results) return;
|
||||
|
||||
const autocomplete = d.querySelector(".autocomplete");
|
||||
const autocompleteList = d.querySelector(".autocomplete ul");
|
||||
autocomplete.classList.add("open");
|
||||
autocompleteList.innerHTML = "";
|
||||
|
||||
// show an error message that no result was found
|
||||
if (!results[1] || results[1].length == 0) {
|
||||
const noItemFoundMessage = document.createElement("li");
|
||||
noItemFoundMessage.classList.add('no-item-found');
|
||||
noItemFoundMessage.innerHTML = searxng.settings.translations.no_item_found;
|
||||
autocompleteList.appendChild(noItemFoundMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
for (let result of results[1]) {
|
||||
const li = document.createElement("li");
|
||||
li.innerText = result;
|
||||
|
||||
searxng.on(li, 'mousedown', () => {
|
||||
qinput.value = result;
|
||||
const form = d.querySelector("#search");
|
||||
form.submit();
|
||||
autocomplete.classList.remove('open');
|
||||
});
|
||||
autocompleteList.appendChild(li);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
searxng.ready(function () {
|
||||
// focus search input on large screens
|
||||
if (!isMobile && !isResultsPage) document.getElementById("q").focus();
|
||||
|
||||
qinput = d.getElementById(qinput_id);
|
||||
const autocomplete = d.querySelector(".autocomplete");
|
||||
const autocompleteList = d.querySelector(".autocomplete ul");
|
||||
|
||||
if (qinput !== null) {
|
||||
// clear button
|
||||
createClearButton(qinput);
|
||||
|
||||
// autocompleter
|
||||
if (searxng.settings.autocomplete) {
|
||||
searxng.on(qinput, 'input', () => {
|
||||
const query = qinput.value;
|
||||
if (query.length < searxng.settings.autocomplete_min) return;
|
||||
|
||||
setTimeout(() => {
|
||||
if (query == qinput.value) fetchResults(query);
|
||||
}, 300);
|
||||
});
|
||||
|
||||
searxng.on(qinput, 'keyup', (e) => {
|
||||
let currentIndex = -1;
|
||||
const listItems = autocompleteList.children;
|
||||
for (let i = 0; i < listItems.length; i++) {
|
||||
if (listItems[i].classList.contains('active')) {
|
||||
currentIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let newCurrentIndex = -1;
|
||||
if (e.key === "ArrowUp") {
|
||||
if (currentIndex >= 0) listItems[currentIndex].classList.remove('active');
|
||||
// we need to add listItems.length to the index calculation here because the JavaScript modulos
|
||||
// operator doesn't work with negative numbers
|
||||
newCurrentIndex = (currentIndex - 1 + listItems.length) % listItems.length;
|
||||
} else if (e.key === "ArrowDown") {
|
||||
if (currentIndex >= 0) listItems[currentIndex].classList.remove('active');
|
||||
newCurrentIndex = (currentIndex + 1) % listItems.length;
|
||||
} else if (e.key === "Tab" || e.key === "Enter") {
|
||||
autocomplete.classList.remove('open');
|
||||
}
|
||||
|
||||
if (newCurrentIndex != -1) {
|
||||
const selectedItem = listItems[newCurrentIndex];
|
||||
selectedItem.classList.add('active');
|
||||
|
||||
if (!selectedItem.classList.contains('no-item-found')) qinput.value = selectedItem.innerText;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Additionally to searching when selecting a new category, we also
|
||||
// automatically start a new search request when the user changes a search
|
||||
// filter (safesearch, time range or language) (this requires JavaScript
|
||||
// though)
|
||||
if (
|
||||
qinput !== null
|
||||
&& searxng.settings.search_on_category_select
|
||||
// If .search_filters is undefined (invisible) we are on the homepage and
|
||||
// hence don't have to set any listeners
|
||||
&& d.querySelector(".search_filters") != null
|
||||
) {
|
||||
searxng.on(d.getElementById('safesearch'), 'change', submitIfQuery);
|
||||
searxng.on(d.getElementById('time_range'), 'change', submitIfQuery);
|
||||
searxng.on(d.getElementById('language'), 'change', submitIfQuery);
|
||||
}
|
||||
|
||||
const categoryButtons = d.querySelectorAll("button.category_button");
|
||||
for (let button of categoryButtons) {
|
||||
searxng.on(button, 'click', (event) => {
|
||||
if (event.shiftKey) {
|
||||
event.preventDefault();
|
||||
button.classList.toggle("selected");
|
||||
return;
|
||||
}
|
||||
|
||||
// manually deselect the old selection when a new category is selected
|
||||
const selectedCategories = d.querySelectorAll("button.category_button.selected");
|
||||
for (let categoryButton of selectedCategories) {
|
||||
categoryButton.classList.remove("selected");
|
||||
}
|
||||
button.classList.add("selected");
|
||||
});
|
||||
}
|
||||
|
||||
// override form submit action to update the actually selected categories
|
||||
const form = d.querySelector("#search");
|
||||
if (form != null) {
|
||||
searxng.on(form, 'submit', (event) => {
|
||||
event.preventDefault();
|
||||
const categoryValuesInput = d.querySelector("#selected-categories");
|
||||
if (categoryValuesInput) {
|
||||
let categoryValues = [];
|
||||
for (let categoryButton of categoryButtons) {
|
||||
if (categoryButton.classList.contains("selected")) {
|
||||
categoryValues.push(categoryButton.name.replace("category_", ""));
|
||||
}
|
||||
}
|
||||
categoryValuesInput.value = categoryValues.join(",");
|
||||
}
|
||||
form.submit();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
})(window, document, window.searxng);
|
|
@ -1 +0,0 @@
|
|||
import "./head/00_init.js";
|
|
@ -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";
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 |
|
@ -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 |
|
@ -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 |
2
client/simple/static/.gitattributes
vendored
2
client/simple/static/.gitattributes
vendored
|
@ -1,2 +0,0 @@
|
|||
leaflet.css -diff
|
||||
leaflet.js -diff
|
|
@ -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);
|
|
@ -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 };
|
|
@ -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
|
|
@ -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,
|
||||
};
|
|
@ -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 };
|
|
@ -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
|
||||
|
||||
});
|
|
@ -1,65 +0,0 @@
|
|||
FROM ghcr.io/searxng/base:searxng-builder AS builder
|
||||
|
||||
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"
|
||||
|
||||
RUN python -m compileall -q searx \
|
||||
&& touch -c --date=@$TIMESTAMP_SETTINGS ./searx/settings.yml \
|
||||
&& find ./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 {} +
|
||||
|
||||
FROM ghcr.io/searxng/base:searxng AS dist
|
||||
|
||||
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"
|
||||
|
||||
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/config/ ./.template/
|
||||
COPY --chown=searxng:searxng ./container/entrypoint.sh ./entrypoint.sh
|
||||
|
||||
ARG TIMESTAMP_UWSGI="0"
|
||||
|
||||
RUN touch -c --date=@$TIMESTAMP_UWSGI ./.template/uwsgi.ini
|
||||
|
||||
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 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/entrypoint.sh"]
|
|
@ -1,25 +0,0 @@
|
|||
contents:
|
||||
keyring:
|
||||
- https://packages.wolfi.dev/os/wolfi-signing.rsa.pub
|
||||
repositories:
|
||||
- https://packages.wolfi.dev/os
|
||||
packages:
|
||||
- wolfi-base
|
||||
- build-base
|
||||
- python-3.13-dev
|
||||
- py3-pip
|
||||
- brotli
|
||||
|
||||
entrypoint:
|
||||
command: /bin/sh -l
|
||||
|
||||
work-dir: /usr/local/searxng/
|
||||
|
||||
environment:
|
||||
PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
|
||||
HISTFILE: /dev/null
|
||||
|
||||
archs:
|
||||
- x86_64
|
||||
- aarch64
|
|
@ -1,61 +0,0 @@
|
|||
contents:
|
||||
keyring:
|
||||
- https://packages.wolfi.dev/os/wolfi-signing.rsa.pub
|
||||
repositories:
|
||||
- https://packages.wolfi.dev/os
|
||||
packages:
|
||||
- wolfi-baselayout
|
||||
- ca-certificates-bundle
|
||||
- busybox
|
||||
- python-3.13
|
||||
# healthcheck
|
||||
- wget
|
||||
# uwsgi
|
||||
- mailcap
|
||||
|
||||
entrypoint:
|
||||
command: /bin/sh -l
|
||||
|
||||
work-dir: /usr/local/searxng/
|
||||
|
||||
accounts:
|
||||
groups:
|
||||
- groupname: searxng
|
||||
gid: 977
|
||||
users:
|
||||
- username: searxng
|
||||
uid: 977
|
||||
shell: /bin/ash
|
||||
|
||||
environment:
|
||||
PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
|
||||
HISTFILE: /dev/null
|
||||
CONFIG_PATH: /etc/searxng
|
||||
DATA_PATH: /var/cache/searxng
|
||||
|
||||
paths:
|
||||
# Workdir
|
||||
- path: /usr/local/searxng/
|
||||
type: directory
|
||||
uid: 977
|
||||
gid: 977
|
||||
permissions: 0o755
|
||||
|
||||
# Config volume
|
||||
- path: /etc/searxng/
|
||||
type: directory
|
||||
uid: 977
|
||||
gid: 977
|
||||
permissions: 0o755
|
||||
|
||||
# Data volume
|
||||
- path: /var/cache/searxng/
|
||||
type: directory
|
||||
uid: 977
|
||||
gid: 977
|
||||
permissions: 0o755
|
||||
|
||||
archs:
|
||||
- x86_64
|
||||
- aarch64
|
|
@ -1,166 +0,0 @@
|
|||
#!/bin/sh
|
||||
# shellcheck shell=dash
|
||||
set -u
|
||||
|
||||
check_file() {
|
||||
local target="$1"
|
||||
|
||||
if [ ! -f "$target" ]; then
|
||||
cat <<EOF
|
||||
!!!
|
||||
!!! ERROR
|
||||
!!! "$target" is not a valid file, exiting...
|
||||
!!!
|
||||
EOF
|
||||
exit 127
|
||||
fi
|
||||
}
|
||||
|
||||
check_directory() {
|
||||
local target="$1"
|
||||
|
||||
if [ ! -d "$target" ]; then
|
||||
cat <<EOF
|
||||
!!!
|
||||
!!! ERROR
|
||||
!!! "$target" is not a valid directory, exiting...
|
||||
!!!
|
||||
EOF
|
||||
exit 127
|
||||
fi
|
||||
}
|
||||
|
||||
setup_ownership() {
|
||||
local target="$1"
|
||||
local type="$2"
|
||||
|
||||
case "$type" in
|
||||
file | directory) ;;
|
||||
*)
|
||||
cat <<EOF
|
||||
!!!
|
||||
!!! ERROR
|
||||
!!! "$type" is not a valid type, exiting...
|
||||
!!!
|
||||
EOF
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$(stat -c %U:%G "$target")" != "searxng:searxng" ]; then
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
chown -R searxng:searxng "$target"
|
||||
else
|
||||
cat <<EOF
|
||||
!!!
|
||||
!!! WARNING
|
||||
!!! "$target" $type is not owned by "searxng"
|
||||
!!! This may cause issues when running SearXNG
|
||||
!!!
|
||||
!!! Run the container as root to fix this issue automatically
|
||||
!!! Alternatively, you can chown the $type manually:
|
||||
!!! $ chown -R searxng:searxng "$target"
|
||||
!!!
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Apply envs to uwsgi.ini
|
||||
setup_uwsgi() {
|
||||
local timestamp
|
||||
|
||||
timestamp=$(stat -c %Y "$UWSGI_SETTINGS_PATH")
|
||||
|
||||
sed -i \
|
||||
-e "s|workers = .*|workers = ${UWSGI_WORKERS:-%k}|g" \
|
||||
-e "s|threads = .*|threads = ${UWSGI_THREADS:-4}|g" \
|
||||
"$UWSGI_SETTINGS_PATH"
|
||||
|
||||
# Restore timestamp
|
||||
touch -c -d "@$timestamp" "$UWSGI_SETTINGS_PATH"
|
||||
}
|
||||
|
||||
# Apply envs to settings.yml
|
||||
setup_searxng() {
|
||||
local timestamp
|
||||
|
||||
timestamp=$(stat -c %Y "$SEARXNG_SETTINGS_PATH")
|
||||
|
||||
# Ensure trailing slash in BASE_URL
|
||||
# https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Parameter-Expansion
|
||||
export BASE_URL="${BASE_URL%/}/"
|
||||
|
||||
sed -i \
|
||||
-e "s|base_url: false|base_url: ${BASE_URL:-false}|g" \
|
||||
-e "s/instance_name: \"SearXNG\"/instance_name: \"${INSTANCE_NAME:-SearXNG}\"/g" \
|
||||
-e "s/autocomplete: \"\"/autocomplete: \"${AUTOCOMPLETE:-}\"/g" \
|
||||
-e "s/ultrasecretkey/$(head -c 24 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9')/g" \
|
||||
"$SEARXNG_SETTINGS_PATH"
|
||||
|
||||
# Restore timestamp
|
||||
touch -c -d "@$timestamp" "$SEARXNG_SETTINGS_PATH"
|
||||
}
|
||||
|
||||
# Handle volume mounts
|
||||
volume_handler() {
|
||||
local target="$1"
|
||||
|
||||
# Check if it's a valid directory
|
||||
check_directory "$target"
|
||||
setup_ownership "$target" "directory"
|
||||
}
|
||||
|
||||
# Handle configuration file updates
|
||||
config_handler() {
|
||||
local target="$1"
|
||||
local template="$2"
|
||||
local new_template_target="$target.new"
|
||||
|
||||
# Create/Update the configuration file
|
||||
if [ -f "$target" ]; then
|
||||
setup_ownership "$target" "file"
|
||||
|
||||
if [ "$template" -nt "$target" ]; then
|
||||
cp -pfT "$template" "$new_template_target"
|
||||
|
||||
cat <<EOF
|
||||
...
|
||||
... INFORMATION
|
||||
... Update available for "$target"
|
||||
... It is recommended to update the configuration file to ensure proper functionality
|
||||
...
|
||||
... New version placed at "$new_template_target"
|
||||
... Please review and merge changes
|
||||
...
|
||||
EOF
|
||||
fi
|
||||
else
|
||||
cat <<EOF
|
||||
...
|
||||
... INFORMATION
|
||||
... "$target" does not exist, creating from template...
|
||||
...
|
||||
EOF
|
||||
cp -pfT "$template" "$target"
|
||||
fi
|
||||
|
||||
# Check if it's a valid file
|
||||
check_file "$target"
|
||||
}
|
||||
|
||||
echo "SearXNG $SEARXNG_VERSION"
|
||||
|
||||
# Check for volume mounts
|
||||
volume_handler "$CONFIG_PATH"
|
||||
volume_handler "$DATA_PATH"
|
||||
|
||||
# Check for updates in files
|
||||
config_handler "$UWSGI_SETTINGS_PATH" "/usr/local/searxng/.template/uwsgi.ini"
|
||||
config_handler "$SEARXNG_SETTINGS_PATH" "/usr/local/searxng/searx/settings.yml"
|
||||
|
||||
# Update files
|
||||
setup_uwsgi
|
||||
setup_searxng
|
||||
|
||||
exec /usr/local/searxng/venv/bin/uwsgi --http-socket "$BIND_ADDRESS" "$UWSGI_SETTINGS_PATH"
|
|
@ -1,107 +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 \
|
||||
# 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
|
||||
|
||||
RUN python -m compileall -q searx \
|
||||
&& touch -c --date=@$TIMESTAMP_SETTINGS ./searx/settings.yml \
|
||||
&& 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/config/ ./.template/
|
||||
COPY --chown=searxng:searxng ./container/entrypoint.sh ./entrypoint.sh
|
||||
|
||||
ARG TIMESTAMP_UWSGI="0"
|
||||
|
||||
RUN touch -c --date=@$TIMESTAMP_UWSGI ./.template/uwsgi.ini
|
||||
|
||||
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/entrypoint.sh"]
|
178
dockerfiles/docker-entrypoint.sh
Executable file
178
dockerfiles/docker-entrypoint.sh
Executable file
|
@ -0,0 +1,178 @@
|
|||
#!/bin/sh
|
||||
|
||||
help() {
|
||||
cat <<EOF
|
||||
Command line:
|
||||
-h Display this help
|
||||
-d Dry run to update the configuration files.
|
||||
-f Always update on the configuration files (existing files are renamed with
|
||||
the .old suffix). Without this option, the new configuration files are
|
||||
copied with the .new suffix
|
||||
Environment variables:
|
||||
INSTANCE_NAME settings.yml : general.instance_name
|
||||
AUTOCOMPLETE settings.yml : search.autocomplete
|
||||
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:
|
||||
/etc/searxng the docker entry point copies settings.yml and uwsgi.ini in
|
||||
this directory (see the -f command line option)"
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
export DEFAULT_BIND_ADDRESS="0.0.0.0:8080"
|
||||
export BIND_ADDRESS="${BIND_ADDRESS:-${DEFAULT_BIND_ADDRESS}}"
|
||||
|
||||
# Parse command line
|
||||
FORCE_CONF_UPDATE=0
|
||||
DRY_RUN=0
|
||||
|
||||
while getopts "fdh" option
|
||||
do
|
||||
case $option in
|
||||
|
||||
f) FORCE_CONF_UPDATE=1 ;;
|
||||
d) DRY_RUN=1 ;;
|
||||
|
||||
h)
|
||||
help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "unknow option ${option}"
|
||||
exit 42
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
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
|
||||
patch_uwsgi_settings() {
|
||||
CONF="$1"
|
||||
|
||||
# update uwsg.ini
|
||||
sed -i \
|
||||
-e "s|workers = .*|workers = ${UWSGI_WORKERS:-%k}|g" \
|
||||
-e "s|threads = .*|threads = ${UWSGI_THREADS:-4}|g" \
|
||||
"${CONF}"
|
||||
}
|
||||
|
||||
patch_searxng_settings() {
|
||||
CONF="$1"
|
||||
|
||||
# Make sure that there is trailing slash at the end of BASE_URL
|
||||
# see https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Parameter-Expansion
|
||||
export BASE_URL="${BASE_URL%/}/"
|
||||
|
||||
# update settings.yml
|
||||
sed -i \
|
||||
-e "s|base_url: false|base_url: ${BASE_URL}|g" \
|
||||
-e "s/instance_name: \"SearXNG\"/instance_name: \"${INSTANCE_NAME}\"/g" \
|
||||
-e "s/autocomplete: \"\"/autocomplete: \"${AUTOCOMPLETE}\"/g" \
|
||||
-e "s/ultrasecretkey/$(openssl rand -hex 32)/g" \
|
||||
"${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() {
|
||||
FORCE_CONF_UPDATE=$1
|
||||
CONF="$2"
|
||||
NEW_CONF="${2}.new"
|
||||
OLD_CONF="${2}.old"
|
||||
REF_CONF="$3"
|
||||
PATCH_REF_CONF="$4"
|
||||
|
||||
if [ -f "${CONF}" ]; then
|
||||
if [ "${REF_CONF}" -nt "${CONF}" ]; then
|
||||
# There is a new version
|
||||
if [ "$FORCE_CONF_UPDATE" -ne 0 ]; then
|
||||
# Replace the current configuration
|
||||
printf '⚠️ Automatically update %s to the new version\n' "${CONF}"
|
||||
if [ ! -f "${OLD_CONF}" ]; then
|
||||
printf 'The previous configuration is saved to %s\n' "${OLD_CONF}"
|
||||
mv "${CONF}" "${OLD_CONF}"
|
||||
fi
|
||||
cp "${REF_CONF}" "${CONF}"
|
||||
$PATCH_REF_CONF "${CONF}"
|
||||
else
|
||||
# Keep the current configuration
|
||||
printf '⚠️ Check new version %s to make sure SearXNG is working properly\n' "${NEW_CONF}"
|
||||
cp "${REF_CONF}" "${NEW_CONF}"
|
||||
$PATCH_REF_CONF "${NEW_CONF}"
|
||||
fi
|
||||
else
|
||||
printf 'Use existing %s\n' "${CONF}"
|
||||
fi
|
||||
else
|
||||
printf 'Create %s\n' "${CONF}"
|
||||
cp "${REF_CONF}" "${CONF}"
|
||||
$PATCH_REF_CONF "${CONF}"
|
||||
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
|
||||
update_conf "${FORCE_CONF_UPDATE}" "${UWSGI_SETTINGS_PATH}" "/usr/local/searxng/dockerfiles/uwsgi.ini" "patch_uwsgi_settings"
|
||||
|
||||
# make sure there are searxng settings
|
||||
update_conf "${FORCE_CONF_UPDATE}" "${SEARXNG_SETTINGS_PATH}" "/usr/local/searxng/searx/settings.yml" "patch_searxng_settings"
|
||||
|
||||
# dry run (to update configuration files, then inspect them)
|
||||
if [ $DRY_RUN -eq 1 ]; then
|
||||
printf 'Dry run\n'
|
||||
exit
|
||||
fi
|
||||
|
||||
unset MORTY_KEY
|
||||
|
||||
# Start uwsgi
|
||||
printf 'Listen on %s\n' "${BIND_ADDRESS}"
|
||||
exec uwsgi --master --uid searxng --gid searxng --http-socket "${BIND_ADDRESS}" "${UWSGI_SETTINGS_PATH}"
|
|
@ -1,8 +1,4 @@
|
|||
[uwsgi]
|
||||
# Listening address
|
||||
# default value: [::]:8080 (see Dockerfile)
|
||||
http-socket = $(BIND_ADDRESS)
|
||||
|
||||
# Who will run the code
|
||||
uid = searxng
|
||||
gid = searxng
|
||||
|
@ -21,6 +17,7 @@ chmod-socket = 666
|
|||
# Plugin to use and interpreter config
|
||||
single-interpreter = true
|
||||
master = true
|
||||
plugin = python3
|
||||
lazy-apps = true
|
||||
enable-threads = true
|
||||
|
||||
|
@ -51,5 +48,7 @@ die-on-term
|
|||
|
||||
# uwsgi serves the static files
|
||||
static-map = /static=/usr/local/searxng/searx/static
|
||||
# expires set to one day
|
||||
static-expires = /* 86400
|
||||
static-gzip-all = True
|
||||
offload-threads = %k
|
|
@ -6,7 +6,7 @@ digraph G {
|
|||
browser [label="browser", shape=tab, fillcolor=aliceblue];
|
||||
rp [label="reverse proxy"];
|
||||
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];
|
||||
searxng1 [label="SearXNG #1", fontcolor=blue3];
|
||||
searxng2 [label="SearXNG #2", fontcolor=blue3];
|
||||
|
|
|
@ -145,6 +145,13 @@ shell inside container
|
|||
- `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>`_
|
||||
|
||||
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:
|
||||
|
||||
.. code:: sh
|
||||
|
@ -181,10 +188,10 @@ Command line
|
|||
<https://docs.docker.com/engine/reference/run/#foreground>`__.
|
||||
|
||||
In the :origin:`Dockerfile` the ENTRYPOINT_ is defined as
|
||||
:origin:`container/entrypoint.sh`
|
||||
:origin:`dockerfiles/docker-entrypoint.sh`
|
||||
|
||||
.. code:: sh
|
||||
|
||||
docker run --rm -it searxng/searxng -h
|
||||
|
||||
.. program-output:: ../container/entrypoint.sh -h
|
||||
.. program-output:: ../dockerfiles/docker-entrypoint.sh -h
|
||||
|
|
|
@ -96,7 +96,7 @@ Modify the ``/etc/searxng/settings.yml`` to your needs:
|
|||
|
||||
.. literalinclude:: ../../utils/templates/etc/searxng/settings.yml
|
||||
:language: yaml
|
||||
:end-before: # preferences:
|
||||
:end-before: # hostnames:
|
||||
|
||||
To see the entire file jump to :origin:`utils/templates/etc/searxng/settings.yml`
|
||||
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
.. _plugins admin:
|
||||
.. _plugins generic:
|
||||
|
||||
===============
|
||||
List of plugins
|
||||
Plugins builtin
|
||||
===============
|
||||
|
||||
Further reading ..
|
||||
.. sidebar:: Further reading ..
|
||||
|
||||
- :ref:`SearXNG settings <settings plugins>`
|
||||
- :ref:`dev plugin`
|
||||
|
||||
Configuration defaults (at built time):
|
||||
|
||||
:DO: Default on
|
||||
|
||||
.. _configured plugins:
|
||||
|
||||
.. jinja:: searx
|
||||
|
@ -19,13 +22,18 @@ Further reading ..
|
|||
:widths: 3 1 9
|
||||
|
||||
* - Name
|
||||
- Active
|
||||
- DO
|
||||
- Description
|
||||
|
||||
{% for plg in plugins %}
|
||||
JS & CSS dependencies
|
||||
|
||||
* - {{plg.info.name}}
|
||||
- {{(plg.active and "yes") or "no"}}
|
||||
- {{plg.info.description}}
|
||||
{% for plgin in plugins %}
|
||||
|
||||
* - {{plgin.name}}
|
||||
- {{(plgin.default_on and "y") or ""}}
|
||||
- {{plgin.description}}
|
||||
|
||||
{% for dep in (plgin.js_dependencies + plgin.css_dependencies) %}
|
||||
| ``{{dep}}`` {% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
|
|
|
@ -93,13 +93,15 @@ TOML_ configuration is created in the file ``/etc/searxng/favicons.toml``.
|
|||
: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``.
|
||||
production environment. The FHS_ provides the folder for the
|
||||
application cache
|
||||
|
||||
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.
|
||||
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 container systems, a volume should be mounted for this folder and 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
|
||||
|
||||
|
@ -107,10 +109,6 @@ TOML_ configuration is created in the file ``/etc/searxng/favicons.toml``.
|
|||
$ 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
|
||||
|
|
|
@ -13,7 +13,7 @@ Settings
|
|||
:maxdepth: 2
|
||||
|
||||
settings
|
||||
settings_engines
|
||||
settings_engine
|
||||
settings_brand
|
||||
settings_general
|
||||
settings_search
|
||||
|
@ -22,6 +22,6 @@ Settings
|
|||
settings_redis
|
||||
settings_outgoing
|
||||
settings_categories_as_tabs
|
||||
settings_plugins
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ and can relied on the default configuration :origin:`searx/settings.yml` using:
|
|||
use_default_settings: true
|
||||
server:
|
||||
secret_key: "ultrasecretkey" # change this!
|
||||
bind_address: "[::]"
|
||||
bind_address: "0.0.0.0"
|
||||
|
||||
``engines:``
|
||||
With ``use_default_settings: true``, each settings can be override in a
|
||||
|
|
|
@ -1,30 +1,14 @@
|
|||
.. _settings engines:
|
||||
.. _settings engine:
|
||||
|
||||
============
|
||||
``engines:``
|
||||
============
|
||||
===========
|
||||
``engine:``
|
||||
===========
|
||||
|
||||
.. sidebar:: Further reading ..
|
||||
|
||||
- :ref:`configured engines`
|
||||
- :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
|
||||
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
|
||||
|
||||
- name: example
|
||||
- name: example engine
|
||||
engine: example
|
||||
shortcut: demo
|
||||
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``
|
||||
When an engine returns an error, the message is displayed on the user interface.
|
||||
|
||||
.. _engine network:
|
||||
|
||||
``network`` : optional
|
||||
Use the network configuration from another engine.
|
||||
In addition, there are two default networks:
|
||||
|
@ -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
|
||||
"google english" will return English results.
|
||||
|
|
@ -16,14 +16,8 @@
|
|||
open_metrics: ''
|
||||
|
||||
``debug`` : ``$SEARXNG_DEBUG``
|
||||
In debug mode, the server provides an interactive debugger, will reload when
|
||||
code is changed and activates a verbose logging.
|
||||
|
||||
.. attention::
|
||||
|
||||
The debug setting is intended for local development server. Don't
|
||||
activate debug (don't use a development server) when deploying to
|
||||
production.
|
||||
Allow a more detailed log if you run SearXNG directly. Display *detailed* error
|
||||
messages in the browser too, so this must be deactivated in production.
|
||||
|
||||
``donation_url`` :
|
||||
Set value to ``true`` to use your own donation page written in the
|
||||
|
|
|
@ -43,7 +43,7 @@ Communication with search engines.
|
|||
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
|
||||
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`` :
|
||||
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 (``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`
|
||||
|
||||
|
||||
|
|
|
@ -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`_
|
||||
- ..
|
|
@ -12,7 +12,6 @@
|
|||
favicon_resolver: ""
|
||||
default_lang: ""
|
||||
ban_time_on_fail: 5
|
||||
max_page: 0
|
||||
max_ban_time_on_fail: 120
|
||||
suspended_times:
|
||||
SearxEngineAccessDenied: 86400
|
||||
|
@ -34,22 +33,14 @@
|
|||
``autocomplete``:
|
||||
Existing autocomplete backends, leave blank to turn it off.
|
||||
|
||||
- ``360search``
|
||||
- ``baidu``
|
||||
- ``brave``
|
||||
- ``dbpedia``
|
||||
- ``duckduckgo``
|
||||
- ``google``
|
||||
- ``mwmbl``
|
||||
- ``naver``
|
||||
- ``quark``
|
||||
- ``qwant``
|
||||
- ``seznam``
|
||||
- ``sogou``
|
||||
- ``stract``
|
||||
- ``startpage``
|
||||
- ``swisscows``
|
||||
- ``qwant``
|
||||
- ``wikipedia``
|
||||
- ``yandex``
|
||||
|
||||
``favicon_resolver``:
|
||||
To activate favicons in SearXNG's result list select a default
|
||||
|
@ -58,11 +49,11 @@
|
|||
|
||||
``default_lang``:
|
||||
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``:
|
||||
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
|
||||
(in most cases, it is meant to send the query without a language parameter ;
|
||||
in some cases, it means the English language) Example:
|
||||
|
@ -78,11 +69,6 @@
|
|||
- fr
|
||||
- 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 in seconds after engine errors.
|
||||
|
||||
|
|
|
@ -14,14 +14,13 @@
|
|||
limiter: false
|
||||
public_instance: false
|
||||
image_proxy: false
|
||||
method: "POST"
|
||||
default_http_headers:
|
||||
X-Content-Type-Options : nosniff
|
||||
X-Download-Options : noopen
|
||||
X-Robots-Tag : noindex, nofollow
|
||||
Referrer-Policy : no-referrer
|
||||
|
||||
``base_url`` : ``$SEARXNG_BASE_URL``
|
||||
``base_url`` : ``$SEARXNG_URL``
|
||||
The base URL where SearXNG is deployed. Used to create correct inbound links.
|
||||
|
||||
``port`` & ``bind_address``: ``$SEARXNG_PORT`` & ``$SEARXNG_BIND_ADDRESS``
|
||||
|
@ -29,8 +28,6 @@
|
|||
directly using ``python searx/webapp.py``. Doesn't apply to a SearXNG
|
||||
services running behind a proxy and using socket communications.
|
||||
|
||||
.. _server.secret_key:
|
||||
|
||||
``secret_key`` : ``$SEARXNG_SECRET``
|
||||
Used for cryptography purpose.
|
||||
|
||||
|
@ -53,11 +50,6 @@
|
|||
``image_proxy`` : ``$SEARXNG_IMAGE_PROXY``
|
||||
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
|
||||
|
||||
``default_http_headers`` :
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
``center_alignment`` : default ``false``
|
||||
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*
|
||||
(:origin:`min-width: @tablet <client/simple/src/less/definitions.less>`)
|
||||
(:origin:`min-width: @tablet <searx/static/themes/simple/src/less/definitions.less>`)
|
||||
|
||||
.. cache_url:
|
||||
|
||||
|
|
|
@ -58,6 +58,9 @@ and then, to name just a few:
|
|||
- Bot protection has been switched from filtron to SearXNG's :ref:`limiter
|
||||
<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 get in use, the ``static-expires`` needs to be set in the :ref:`uwsgi
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
|
||||
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
|
||||
------------------------
|
||||
|
||||
|
@ -88,6 +130,9 @@ to see if there are some left overs. In this example there exists a *old*
|
|||
SearXNG checks
|
||||
--------------
|
||||
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 : connected to Redis
|
||||
|
|
16
docs/conf.py
16
docs/conf.py
|
@ -54,7 +54,7 @@ searx.engines.load_engines(searx.settings['engines'])
|
|||
jinja_contexts = {
|
||||
'searx': {
|
||||
'engines': searx.engines.engines,
|
||||
'plugins': searx.plugins.STORAGE,
|
||||
'plugins': searx.plugins.plugins,
|
||||
'version': {
|
||||
'node': os.getenv('NODE_MINIMUM_VERSION')
|
||||
},
|
||||
|
@ -127,11 +127,11 @@ extensions = [
|
|||
"sphinx_tabs.tabs", # https://github.com/djungelorm/sphinx-tabs
|
||||
'myst_parser', # https://www.sphinx-doc.org/en/master/usage/markdown.html
|
||||
'notfound.extension', # https://github.com/readthedocs/sphinx-notfound-page
|
||||
'sphinxcontrib.autodoc_pydantic', # https://github.com/mansenfranzen/autodoc_pydantic
|
||||
]
|
||||
|
||||
# autodoc_typehints = "description"
|
||||
autodoc_default_options = {
|
||||
'member-order': 'bysource',
|
||||
'member-order': 'groupwise',
|
||||
}
|
||||
|
||||
myst_enable_extensions = [
|
||||
|
@ -143,10 +143,10 @@ suppress_warnings = ['myst.domains']
|
|||
intersphinx_mapping = {
|
||||
"python": ("https://docs.python.org/3/", 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),
|
||||
"werkzeug": ("https://werkzeug.palletsprojects.com/en/stable/", None),
|
||||
"jinja": ("https://jinja.palletsprojects.com/en/stable/", None),
|
||||
# "werkzeug": ("https://werkzeug.palletsprojects.com/", None),
|
||||
"jinja": ("https://jinja.palletsprojects.com/", None),
|
||||
"linuxdoc" : ("https://return42.github.io/linuxdoc/", None),
|
||||
"sphinx" : ("https://www.sphinx-doc.org/en/master/", None),
|
||||
"redis": ('https://redis.readthedocs.io/en/stable/', None),
|
||||
|
@ -161,7 +161,7 @@ issues_github_path = "searxng/searxng"
|
|||
notfound_urls_prefix = '/'
|
||||
|
||||
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 = "searxng"
|
||||
|
||||
|
@ -197,7 +197,7 @@ html_sidebars = {
|
|||
],
|
||||
}
|
||||
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_show_sourcelink = True
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
.. _builtin answerers:
|
||||
|
||||
==================
|
||||
Built-in Answerers
|
||||
==================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
random
|
||||
statistics
|
|
@ -1,7 +0,0 @@
|
|||
.. _dev answerers:
|
||||
|
||||
====================
|
||||
Answerer Development
|
||||
====================
|
||||
|
||||
.. automodule:: searx.answerers
|
|
@ -1,9 +0,0 @@
|
|||
=========
|
||||
Answerers
|
||||
=========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
development
|
||||
builtins
|
|
@ -1,8 +0,0 @@
|
|||
.. _answerer.random:
|
||||
|
||||
======
|
||||
Random
|
||||
======
|
||||
|
||||
.. autoclass:: searx.answerers.random.SXNGAnswerer
|
||||
:members:
|
|
@ -1,8 +0,0 @@
|
|||
.. _answerer.statistics:
|
||||
|
||||
==========
|
||||
Statistics
|
||||
==========
|
||||
|
||||
.. autoclass:: searx.answerers.statistics.SXNGAnswerer
|
||||
:members:
|
|
@ -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 project’s 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
|
|
@ -27,24 +27,23 @@ Privacy-by-design
|
|||
-----------------
|
||||
|
||||
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.
|
||||
|
||||
Some widely used search engine features may work differently,
|
||||
may be turned off by default, or may not be implemented at all in SearXNG
|
||||
**as a consequence of a privacy-by-design approach**.
|
||||
A few widely used features work differently or turned off by default or not
|
||||
implemented at all **as a consequence of privacy-by-design**.
|
||||
|
||||
Following this approach, features reducing the privacy preserving aspects of SearXNG should be
|
||||
switched off by default or should not be implemented at all. There are plenty of
|
||||
search engines already providing such features. If a feature reduces
|
||||
SearXNG's efficacy in protecting a user's privacy, the user must be informed about
|
||||
the effect of choosing to enable it. Features that protect privacy but differ from the
|
||||
expectations of the user should also be carefully explained to them.
|
||||
If a feature reduces the privacy preserving aspects of searx, it should be
|
||||
switched off by default or should not implemented at all. There are plenty of
|
||||
search engines already providing such features. If a feature reduces the
|
||||
protection of searx, users must be informed about the effect of choosing to
|
||||
enable it. Features that protect privacy but differ from the expectations of
|
||||
the user should also be explained.
|
||||
|
||||
Also, if you think that something works weird with SearXNG, it might be because
|
||||
the tool you are using is designed in a way that interferes with SearXNG's privacy aspects.
|
||||
Also, if you think that something works weird with searx, it's might be because
|
||||
of the tool you use is designed in a way to interfere with the privacy respect.
|
||||
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).
|
||||
|
||||
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/
|
||||
.. _Conventional Commits: https://www.conventionalcommits.org/
|
||||
.. _Git Commit Good Practice: 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!
|
||||
|
||||
- :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:
|
||||
|
||||
|
@ -80,7 +87,15 @@ In order to submit a patch, please follow the steps below:
|
|||
|
||||
- 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.
|
||||
|
||||
|
@ -119,7 +134,7 @@ Here is an example which makes a complete rebuild:
|
|||
|
||||
.. _make docs.live:
|
||||
|
||||
Live build
|
||||
live build
|
||||
----------
|
||||
|
||||
.. _sphinx-autobuild:
|
||||
|
@ -130,8 +145,8 @@ Live build
|
|||
It is recommended to assert a complete rebuild before deploying (use
|
||||
``docs.clean``).
|
||||
|
||||
Live build is like WYSIWYG. It's the recommended way to go if you want to edit the documentation.
|
||||
The Makefile target ``docs.live`` builds the docs, opens
|
||||
Live build is like WYSIWYG. If you want to edit the documentation, its
|
||||
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
|
||||
changed (:ref:`make docs.clean`).
|
||||
|
||||
|
@ -144,9 +159,9 @@ changed (:ref:`make docs.clean`).
|
|||
... Start watching changes
|
||||
|
||||
Live builds are implemented by sphinx-autobuild_. Use environment
|
||||
``$(SPHINXOPTS)`` to pass arguments to the sphinx-autobuild_ command. You can
|
||||
pass any argument except for the ``--host`` option (which is always set to ``0.0.0.0``).
|
||||
E.g., to find and use a free port, use:
|
||||
``$(SPHINXOPTS)`` to pass arguments to the sphinx-autobuild_ command. Except
|
||||
option ``--host`` (which is always set to ``0.0.0.0``) you can pass any
|
||||
argument. E.g to find and use a free port, use:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ Engine Overview
|
|||
.. sidebar:: Further reading ..
|
||||
|
||||
- :ref:`configured engines`
|
||||
- :ref:`settings engines`
|
||||
- :ref:`settings engine`
|
||||
|
||||
SearXNG is a metasearch-engine_, so it uses different search engines to provide
|
||||
better results.
|
||||
|
@ -63,7 +63,7 @@ Engine File
|
|||
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``)
|
||||
:width: 100%
|
||||
|
@ -237,18 +237,335 @@ 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
|
||||
parsed and a list of results is returned.
|
||||
Result Types (``template``)
|
||||
===========================
|
||||
|
||||
A engine can append result-items of different media-types and different
|
||||
result-types to the result list. The list of the result items is render to HTML
|
||||
by templates. For more details read section:
|
||||
Each result item of an engine can be of different media-types. Currently the
|
||||
following media-types are supported. To set another media-type as
|
||||
:ref:`template default`, the parameter ``template`` must be set to the desired
|
||||
type.
|
||||
|
||||
- :ref:`simple theme templates`
|
||||
- :ref:`result types`
|
||||
.. _template default:
|
||||
|
||||
``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``
|
||||
----------
|
||||
|
||||
.. list-table:: Parameter of the **images** media type
|
||||
:header-rows: 2
|
||||
:width: 100%
|
||||
|
||||
* - result-parameter
|
||||
- Python type
|
||||
- information
|
||||
|
||||
* - template
|
||||
- :py:class:`str`
|
||||
- is set to ``images.html``
|
||||
|
||||
* - url
|
||||
- :py:class:`str`
|
||||
- url to the result site
|
||||
|
||||
* - title
|
||||
- :py:class:`str`
|
||||
- title of the result
|
||||
|
||||
* - content
|
||||
- :py:class:`str`
|
||||
- description of the image
|
||||
|
||||
* - publishedDate
|
||||
- :py:class:`datetime <datetime.datetime>`
|
||||
- time of publish
|
||||
|
||||
* - img_src
|
||||
- :py:class:`str`
|
||||
- url to the result image
|
||||
|
||||
* - thumbnail_src
|
||||
- :py:class:`str`
|
||||
- url to a small-preview image
|
||||
|
||||
* - resolution
|
||||
- :py:class:`str`
|
||||
- the resolution of the image (e.g. ``1920 x 1080`` pixel)
|
||||
|
||||
* - img_format
|
||||
- :py:class:`str`
|
||||
- the format of the image (e.g. ``png``)
|
||||
|
||||
* - filesize
|
||||
- :py:class:`str`
|
||||
- size of bytes in :py:obj:`human readable <searx.humanize_bytes>` notation
|
||||
(e.g. ``MB`` for 1024 \* 1024 Bytes filesize).
|
||||
|
||||
|
||||
.. _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
|
||||
length :py:class:`datetime.timedelta`, duration of result
|
||||
views string, view count in humanized number format
|
||||
========================= =====================================================
|
||||
|
||||
|
||||
.. _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
|
||||
|
||||
|
||||
.. _template packages:
|
||||
|
||||
``packages``
|
||||
------------
|
||||
|
||||
.. list-table:: Parameter of the **packages** media type
|
||||
:header-rows: 2
|
||||
:width: 100%
|
||||
|
||||
* - result-parameter
|
||||
- Python type
|
||||
- information
|
||||
|
||||
* - template
|
||||
- :py:class:`str`
|
||||
- is set to ``packages.html``
|
||||
|
||||
* - title
|
||||
- :py:class:`str`
|
||||
- title of the result
|
||||
|
||||
* - content
|
||||
- :py:class:`str`
|
||||
- abstract
|
||||
|
||||
* - package_name
|
||||
- :py:class:`str`
|
||||
- the name of the package
|
||||
|
||||
* - version
|
||||
- :py:class:`str`
|
||||
- the current version of the package
|
||||
|
||||
* - maintainer
|
||||
- :py:class:`str`
|
||||
- the maintainer or author of the project
|
||||
|
||||
* - publishedDate
|
||||
- :py:class:`datetime <datetime.datetime>`
|
||||
- date of latest update or release
|
||||
|
||||
* - tags
|
||||
- :py:class:`List <list>`\ [\ :py:class:`str`\ ]
|
||||
- free tag list
|
||||
|
||||
* - popularity
|
||||
- :py:class:`str`
|
||||
- the popularity of the package, e.g. rating or download count
|
||||
|
||||
* - license_name
|
||||
- :py:class:`str`
|
||||
- the name of the license
|
||||
|
||||
* - license_url
|
||||
- :py:class:`str`
|
||||
- the web location of a license copy
|
||||
|
||||
* - homepage
|
||||
- :py:class:`str`
|
||||
- the url of the project's homepage
|
||||
|
||||
* - source_code_url
|
||||
- :py:class:`str`
|
||||
- the location of the project's source code
|
||||
|
||||
* - links
|
||||
- :py:class:`dict`
|
||||
- additional links in the form of ``{'link_name': 'http://example.com'}``
|
||||
|
|
|
@ -4,11 +4,17 @@
|
|||
Engine Library
|
||||
==============
|
||||
|
||||
.. contents::
|
||||
:depth: 2
|
||||
:local:
|
||||
:backlinks: entry
|
||||
|
||||
.. automodule:: searx.enginelib
|
||||
:members:
|
||||
|
||||
.. _searx.enginelib.traits:
|
||||
|
||||
|
||||
Engine traits
|
||||
=============
|
||||
|
||||
|
|
|
@ -19,14 +19,6 @@ Engine Implementations
|
|||
engine_overview
|
||||
|
||||
|
||||
ResultList and engines
|
||||
======================
|
||||
|
||||
.. autoclass:: searx.result_types.ResultList
|
||||
|
||||
.. autoclass:: searx.result_types.EngineResults
|
||||
|
||||
|
||||
Engine Types
|
||||
============
|
||||
|
||||
|
@ -53,7 +45,6 @@ Online Engines
|
|||
demo/demo_online
|
||||
xpath
|
||||
mediawiki
|
||||
json_engine
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
.. _json_engine engine:
|
||||
|
||||
============
|
||||
JSON Engine
|
||||
============
|
||||
|
||||
.. contents::
|
||||
:depth: 2
|
||||
:local:
|
||||
:backlinks: entry
|
||||
|
||||
.. automodule:: searx.engines.json_engine
|
||||
:members:
|
|
@ -29,7 +29,7 @@ Programming Interface
|
|||
parameter. This function can be omitted, if there is no need to setup anything
|
||||
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
|
||||
responsible to perform a search and return the results in a presentable
|
||||
format. (Where *presentable* means presentable by the selected result
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
.. _chinaso engine:
|
||||
|
||||
=======
|
||||
ChinaSo
|
||||
=======
|
||||
|
||||
.. automodule:: searx.engines.chinaso
|
||||
:members:
|
|
@ -1,13 +0,0 @@
|
|||
.. _core engine:
|
||||
|
||||
====
|
||||
CORE
|
||||
====
|
||||
|
||||
.. contents::
|
||||
:depth: 2
|
||||
:local:
|
||||
:backlinks: entry
|
||||
|
||||
.. automodule:: searx.engines.core
|
||||
:members:
|
|
@ -1,8 +0,0 @@
|
|||
.. _huggingface engine:
|
||||
|
||||
============
|
||||
Hugging Face
|
||||
============
|
||||
|
||||
.. automodule:: searx.engines.huggingface
|
||||
:members:
|
|
@ -4,5 +4,10 @@
|
|||
Mullvad-Leta
|
||||
============
|
||||
|
||||
.. contents:: Contents
|
||||
:depth: 2
|
||||
:local:
|
||||
:backlinks: entry
|
||||
|
||||
.. automodule:: searx.engines.mullvad_leta
|
||||
:members:
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
.. _reuters engine:
|
||||
|
||||
=======
|
||||
Reuters
|
||||
=======
|
||||
|
||||
.. automodule:: searx.engines.reuters
|
||||
:members:
|
|
@ -1,13 +0,0 @@
|
|||
.. _soundcloud engine:
|
||||
|
||||
==========
|
||||
Soundcloud
|
||||
==========
|
||||
|
||||
.. contents::
|
||||
:depth: 2
|
||||
:local:
|
||||
:backlinks: entry
|
||||
|
||||
.. automodule:: searx.engines.soundcloud
|
||||
:members:
|
|
@ -1,7 +0,0 @@
|
|||
.. _extended_types.:
|
||||
|
||||
==============
|
||||
Extended Types
|
||||
==============
|
||||
|
||||
.. automodule:: searx.extended_types
|
|
@ -6,16 +6,11 @@ Developer documentation
|
|||
:maxdepth: 2
|
||||
|
||||
quickstart
|
||||
commits
|
||||
rtm_asdf
|
||||
contribution_guide
|
||||
extended_types
|
||||
engines/index
|
||||
result_types/index
|
||||
templates
|
||||
search_api
|
||||
plugins/index
|
||||
answerers/index
|
||||
plugins
|
||||
translation
|
||||
lxcdev
|
||||
makefile
|
||||
|
|
|
@ -319,13 +319,13 @@ To *inspect* the SearXNG instance (already described above):
|
|||
|
||||
.. code:: bash
|
||||
|
||||
$ ./utils/searxng.sh inspect service
|
||||
$ ./utils/searx.sh inspect service
|
||||
|
||||
.. group-tab:: desktop (HOST)
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ sudo -H ./utils/lxc.sh cmd searxng-archlinux ./utils/searxng.sh inspect service
|
||||
$ sudo -H ./utils/lxc.sh cmd searxng-archlinux ./utils/searx.sh inspect service
|
||||
|
||||
Run :ref:`makefile`, e.g. to test inside the container:
|
||||
|
||||
|
@ -435,3 +435,4 @@ use:
|
|||
[searxng-archlinux] SEARXNG_URL : http:///n.n.n.140/searxng
|
||||
[searxng-archlinux] SEARXNG_PORT : 8888
|
||||
[searxng-archlinux] SEARXNG_BIND_ADDRESS : 127.0.0.1
|
||||
|
||||
|
|
|
@ -180,9 +180,6 @@ sources of the theme need to be rebuild. You can do that by running::
|
|||
|
||||
$ make themes.all
|
||||
|
||||
..
|
||||
ToDo: vite server is not implemented yet / will be done in a follow up PR
|
||||
|
||||
Alternatively to ``themes.all`` you can run *live builds* of the theme you are
|
||||
modify (:ref:`make themes`)::
|
||||
|
||||
|
|
106
docs/dev/plugins.rst
Normal file
106
docs/dev/plugins.rst
Normal file
|
@ -0,0 +1,106 @@
|
|||
.. _dev plugin:
|
||||
|
||||
=======
|
||||
Plugins
|
||||
=======
|
||||
|
||||
.. sidebar:: Further reading ..
|
||||
|
||||
- :ref:`plugins generic`
|
||||
|
||||
Plugins can extend or replace functionality of various components of searx.
|
||||
|
||||
Example plugin
|
||||
==============
|
||||
|
||||
.. code:: python
|
||||
|
||||
name = 'Example plugin'
|
||||
description = 'This plugin extends the suggestions with the word "example"'
|
||||
default_on = False # disabled by default
|
||||
|
||||
# attach callback to the post search hook
|
||||
# request: flask request object
|
||||
# ctx: the whole local context of the post search hook
|
||||
def post_search(request, search):
|
||||
search.result_container.suggestions.add('example')
|
||||
return True
|
||||
|
||||
External plugins
|
||||
================
|
||||
|
||||
SearXNG supports *external plugins* / there is no need to install one, SearXNG
|
||||
runs out of the box. But to demonstrate; in the example below we install the
|
||||
SearXNG plugins from *The Green Web Foundation* `[ref]
|
||||
<https://www.thegreenwebfoundation.org/news/searching-the-green-web-with-searx/>`__:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ sudo utils/searxng.sh instance cmd bash -c
|
||||
(searxng-pyenv)$ pip install git+https://github.com/return42/tgwf-searx-plugins
|
||||
|
||||
In the :ref:`settings.yml` activate the ``plugins:`` section and add module
|
||||
``only_show_green_results`` from ``tgwf-searx-plugins``.
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
plugins:
|
||||
...
|
||||
- only_show_green_results
|
||||
...
|
||||
|
||||
|
||||
Plugin entry points
|
||||
===================
|
||||
|
||||
Entry points (hooks) define when a plugin runs. Right now only three hooks are
|
||||
implemented. So feel free to implement a hook if it fits the behaviour of your
|
||||
plugin. A plugin doesn't need to implement all the hooks.
|
||||
|
||||
|
||||
.. py:function:: pre_search(request, search) -> bool
|
||||
|
||||
Runs BEFORE the search request.
|
||||
|
||||
`search.result_container` can be changed.
|
||||
|
||||
Return a boolean:
|
||||
|
||||
* True to continue the search
|
||||
* False to stop the search
|
||||
|
||||
:param flask.request request:
|
||||
:param searx.search.SearchWithPlugins search:
|
||||
:return: False to stop the search
|
||||
:rtype: bool
|
||||
|
||||
|
||||
.. py:function:: post_search(request, search) -> None
|
||||
|
||||
Runs AFTER the search request.
|
||||
|
||||
:param flask.request request: Flask request.
|
||||
:param searx.search.SearchWithPlugins search: Context.
|
||||
|
||||
|
||||
.. py:function:: on_result(request, search, result) -> bool
|
||||
|
||||
Runs for each result of each engine.
|
||||
|
||||
`result` can be changed.
|
||||
|
||||
If `result["url"]` is defined, then `result["parsed_url"] = urlparse(result['url'])`
|
||||
|
||||
.. warning::
|
||||
`result["url"]` can be changed, but `result["parsed_url"]` must be updated too.
|
||||
|
||||
Return a boolean:
|
||||
|
||||
* True to keep the result
|
||||
* False to remove the result
|
||||
|
||||
:param flask.request request:
|
||||
:param searx.search.SearchWithPlugins search:
|
||||
:param typing.Dict result: Result, see - :ref:`engine results`
|
||||
:return: True to keep the result
|
||||
:rtype: bool
|
|
@ -1,15 +0,0 @@
|
|||
.. _builtin plugins:
|
||||
|
||||
================
|
||||
Built-in Plugins
|
||||
================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
calculator
|
||||
hash_plugin
|
||||
hostnames
|
||||
self_info
|
||||
tor_check
|
||||
unit_converter
|
|
@ -1,8 +0,0 @@
|
|||
.. _plugins.calculator:
|
||||
|
||||
==========
|
||||
Calculator
|
||||
==========
|
||||
|
||||
.. automodule:: searx.plugins.calculator
|
||||
:members:
|
|
@ -1,7 +0,0 @@
|
|||
.. _dev plugin:
|
||||
|
||||
==================
|
||||
Plugin Development
|
||||
==================
|
||||
|
||||
.. automodule:: searx.plugins
|
|
@ -1,8 +0,0 @@
|
|||
.. _hash_plugin plugin:
|
||||
|
||||
===========
|
||||
Hash Values
|
||||
===========
|
||||
|
||||
.. autoclass:: searx.plugins.hash_plugin.SXNGPlugin
|
||||
:members:
|
|
@ -1,9 +0,0 @@
|
|||
=======
|
||||
Plugins
|
||||
=======
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
development
|
||||
builtins
|
|
@ -1,8 +0,0 @@
|
|||
.. _self_info plugin:
|
||||
|
||||
=========
|
||||
Self-Info
|
||||
=========
|
||||
|
||||
.. autoclass:: searx.plugins.self_info.SXNGPlugin
|
||||
:members:
|
|
@ -6,8 +6,7 @@ Development Quickstart
|
|||
|
||||
.. _npm: https://www.npmjs.com/
|
||||
.. _Node.js: https://nodejs.org/
|
||||
.. _eslint: https://eslint.org/
|
||||
.. _stylelint: https://stylelint.io/
|
||||
|
||||
|
||||
.. sidebar:: further read
|
||||
|
||||
|
@ -40,9 +39,10 @@ to our ":ref:`how to contribute`" guideline.
|
|||
- :ref:`make themes`
|
||||
|
||||
If you implement themes, you will need to setup a :ref:`Node.js environment
|
||||
<make node.env>`. Before you call *make run* (2.), you need to compile the
|
||||
modified styles and JavaScript: ``make node.clean themes.all``. If eslint_ or
|
||||
stylelint_ report some issues, try ``make themes.fix``.
|
||||
<make node.env>`: ``make node.env``
|
||||
|
||||
Before you call *make run* (2.), you need to compile the modified styles and
|
||||
JavaScript: ``make themes.all``
|
||||
|
||||
Alternatively you can also compile selective the theme you have modified,
|
||||
e.g. the *simple* theme.
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
.. _result_types.answer:
|
||||
|
||||
==============
|
||||
Answer Results
|
||||
==============
|
||||
|
||||
The :ref:`area answer results` is an area in which additional information can
|
||||
be displayed.
|
||||
|
||||
.. automodule:: searx.result_types.answer
|
|
@ -1,5 +0,0 @@
|
|||
======
|
||||
Result
|
||||
======
|
||||
|
||||
.. automodule:: searx.result_types._base
|
|
@ -1,34 +0,0 @@
|
|||
.. _result_types.corrections:
|
||||
|
||||
==================
|
||||
Correction Results
|
||||
==================
|
||||
|
||||
.. hint::
|
||||
|
||||
There is still no typing for these result items. The templates can be used as
|
||||
orientation until the final typing is complete.
|
||||
|
||||
The :ref:`area corrections results` shows the user alternative search terms.
|
||||
|
||||
A result of this type is a very simple dictionary with only one key/value pair
|
||||
|
||||
.. code:: python
|
||||
|
||||
{"correction" : "lorem ipsum .."}
|
||||
|
||||
From this simple dict another dict is build up:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# use RawTextQuery to get the corrections URLs with the same bang
|
||||
{"url" : "!bang lorem ipsum ..", "title": "lorem ipsum .." }
|
||||
|
||||
and used in the template :origin:`corrections.html
|
||||
<searx/templates/simple/elements/corrections.html>`:
|
||||
|
||||
title : :py:class:`str`
|
||||
Corrected search term.
|
||||
|
||||
url : :py:class:`str`
|
||||
Not really an URL, its the value to insert in a HTML form for a SearXNG query.
|
|
@ -1,105 +0,0 @@
|
|||
.. _result types:
|
||||
|
||||
============
|
||||
Result Types
|
||||
============
|
||||
|
||||
To understand the typification of the results, let's take a brief look at the
|
||||
structure of SearXNG .. At its core, SearXNG is nothing more than an aggregator
|
||||
that aggregates the results from various sources, renders them via templates and
|
||||
displays them to the user.
|
||||
|
||||
The **sources** can be:
|
||||
|
||||
1. :ref:`engines <engine implementations>`
|
||||
2. :ref:`plugins <dev plugin>`
|
||||
3. :ref:`answerers <dev answerers>`
|
||||
|
||||
The sources provide the results, which are displayed in different **areas**
|
||||
depending on the type of result. The areas are:
|
||||
|
||||
.. _area main results:
|
||||
|
||||
:ref:`area main results <main search results>`
|
||||
It is the main area in which -- as is typical for search engines -- the
|
||||
results that a search engine has found for the search term are displayed.
|
||||
|
||||
.. _area answer results:
|
||||
|
||||
:ref:`area answers <result_types.answer>`
|
||||
This area displays short answers that could be found for the search term.
|
||||
|
||||
.. _area info box:
|
||||
|
||||
:ref:`area info box <result_types.infobox>`
|
||||
An area in which additional information can be displayed, e.g. excerpts from
|
||||
wikipedia or other sources such as maps.
|
||||
|
||||
.. _area suggestions results:
|
||||
|
||||
:ref:`area suggestions <result_types.suggestion>`
|
||||
Suggestions for alternative search terms can be found in this area. These can
|
||||
be clicked on and a search is carried out with these search terms.
|
||||
|
||||
.. _area corrections results:
|
||||
|
||||
:ref:`area corrections <result_types.corrections>`
|
||||
Results in this area are like the suggestion of alternative search terms,
|
||||
which usually result from spelling corrections
|
||||
|
||||
At this point it is important to note that all **sources** can contribute
|
||||
results to all of the areas mentioned above.
|
||||
|
||||
In most cases, however, the :ref:`engines <engine implementations>` will fill
|
||||
the *main results* and the :ref:`answerers <dev answerers>` will generally
|
||||
provide the contributions for the *answer* area. Not necessary to mention here
|
||||
but for a better understanding: the plugins can also filter out or change
|
||||
results from the main results area (e.g. the URL of the link).
|
||||
|
||||
The result items are organized in the :py:obj:`results.ResultContainer` and
|
||||
after all sources have delivered their results, this container is passed to the
|
||||
templating to build a HTML output. The output is usually HTML, but it is also
|
||||
possible to output the result lists as JSON or RSS feed. Thats quite all we need
|
||||
to know before we dive into typification of result items.
|
||||
|
||||
.. hint::
|
||||
|
||||
Typification of result items: we are at the very first beginng!
|
||||
|
||||
The first thing we have to realize is that there is no typification of the
|
||||
result items so far, we have to build it up first .. and that is quite a big
|
||||
task, which we will only be able to accomplish gradually.
|
||||
|
||||
The foundation for the typeless results was laid back in 2013 in the very first
|
||||
commit :commit:`ae9fb1d7d`, and the principle has not changed since then. At
|
||||
the time, the approach was perfectly adequate, but we have since evolved and the
|
||||
demands on SearXNG increase with every feature request.
|
||||
|
||||
**Motivation:** in the meantime, it has become very difficult to develop new
|
||||
features that require structural changes and it is especially hard for newcomers
|
||||
to find their way in this typeless world. As long as the results are only
|
||||
simple key/value dictionaries, it is not even possible for the IDEs to support
|
||||
the application developer in his work.
|
||||
|
||||
**Planning:** The procedure for subsequent typing will have to be based on the
|
||||
circumstances ..
|
||||
|
||||
.. attention::
|
||||
|
||||
As long as there is no type defined for a kind of result the HTML template
|
||||
specify what the properties of a type are.
|
||||
|
||||
In this sense, you will either find a type definition here in the
|
||||
documentation or, if this does not yet exist, a description of the HTML
|
||||
template.
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
base_result
|
||||
main_result
|
||||
answer
|
||||
correction
|
||||
suggestion
|
||||
infobox
|
|
@ -1,59 +0,0 @@
|
|||
.. _result_types.infobox:
|
||||
|
||||
===============
|
||||
Infobox Results
|
||||
===============
|
||||
|
||||
.. hint::
|
||||
|
||||
There is still no typing for these result items. The templates can be used as
|
||||
orientation until the final typing is complete.
|
||||
|
||||
The :ref:`area info box` is an area where addtional infos shown to the user.
|
||||
|
||||
Fields used in the :origin:`infobox.html
|
||||
<searx/templates/simple/elements/infobox.html>`:
|
||||
|
||||
img_src: :py:class:`str`
|
||||
URL of a image or thumbnail that is displayed in the infobox.
|
||||
|
||||
infobox: :py:class:`str`
|
||||
Title of the info box.
|
||||
|
||||
content: :py:class:`str`
|
||||
Text of the info box.
|
||||
|
||||
The infobox has additional subsections for *attributes*, *urls* and
|
||||
*relatedTopics*:
|
||||
|
||||
attributes: :py:class:`List <list>`\ [\ :py:class:`dict`\ ]
|
||||
A list of attributes. An *attribute* is a dictionary with keys:
|
||||
|
||||
- label :py:class:`str`: (mandatory)
|
||||
|
||||
- value :py:class:`str`: (mandatory)
|
||||
|
||||
- image :py:class:`List <list>`\ [\ :py:class:`dict`\ ] (optional)
|
||||
|
||||
A list of images. An *image* is a dictionary with keys:
|
||||
|
||||
- src :py:class:`str`: URL of an image/thumbnail (mandatory)
|
||||
- alt :py:class:`str`: alternative text for the image (mandatory)
|
||||
|
||||
urls: :py:class:`List <list>`\ [\ :py:class:`dict`\ ]
|
||||
A list of links. An *link* is a dictionary with keys:
|
||||
|
||||
- url :py:class:`str`: URL of the link (mandatory)
|
||||
- title :py:class:`str`: Title of the link (mandatory)
|
||||
|
||||
relatedTopics: :py:class:`List <list>`\ [\ :py:class:`dict`\ ]
|
||||
A list of topics. An *topic* is a dictionary with keys:
|
||||
|
||||
- name: :py:class:`str`: (mandatory)
|
||||
|
||||
- suggestions: :py:class:`List <list>`\ [\ :py:class:`dict`\ ] (optional)
|
||||
|
||||
A list of suggestions. A *suggestion* is simple dictionary with just one
|
||||
key/value pair:
|
||||
|
||||
- suggestion: :py:class:`str`: suggested search term (mandatory)
|
|
@ -1,7 +0,0 @@
|
|||
.. _result_types.keyvalue:
|
||||
|
||||
=================
|
||||
Key-Value Results
|
||||
=================
|
||||
|
||||
.. automodule:: searx.result_types.keyvalue
|
|
@ -1,4 +0,0 @@
|
|||
.. _result_types.mainresult:
|
||||
|
||||
.. autoclass:: searx.result_types._base.MainResult
|
||||
:members:
|
|
@ -1,32 +0,0 @@
|
|||
.. _main search results:
|
||||
|
||||
===================
|
||||
Main Search Results
|
||||
===================
|
||||
|
||||
In the :ref:`area main results` the results that a search engine has found for
|
||||
the search term are displayed.
|
||||
|
||||
There is still no typing for all items in the :ref:`main result list`. The
|
||||
following types have been implemented so far ..
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
main/mainresult
|
||||
main/keyvalue
|
||||
|
||||
The :ref:`LegacyResult <LegacyResult>` is used internally for the results that
|
||||
have not yet been typed. The templates can be used as orientation until the
|
||||
final typing is complete.
|
||||
|
||||
- :ref:`template default` / :py:obj:`Result`
|
||||
- :ref:`template images`
|
||||
- :ref:`template videos`
|
||||
- :ref:`template torrent`
|
||||
- :ref:`template map`
|
||||
- :ref:`template paper`
|
||||
- :ref:`template packages`
|
||||
- :ref:`template code`
|
||||
- :ref:`template files`
|
||||
- :ref:`template products`
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue