From d76dd18f3513bb400d0d49249e6d68ce52320cef Mon Sep 17 00:00:00 2001 From: wasikj Date: Mon, 22 Jun 2026 10:57:33 +0200 Subject: [PATCH 1/3] Introduce check for special characters --- .github/workflows/frontend-linting.yml | 5 ++++- .github/workflows/linting.yml | 5 ++++- docs/source/conf.py | 2 +- .../backend_development_introduction.rst | 6 +++--- docs/source/index.rst | 2 +- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/.github/workflows/frontend-linting.yml b/.github/workflows/frontend-linting.yml index 64c46727..4e03ed38 100644 --- a/.github/workflows/frontend-linting.yml +++ b/.github/workflows/frontend-linting.yml @@ -30,4 +30,7 @@ jobs: - name: Run linting working-directory: frontend - run: npm run lint \ No newline at end of file + run: npm run lint + + - name: Check for forbidden Unicode characters + run: bash backend/ci/forbidden-chars-check.sh frontend/ --ext .ts .tsx .js .jsx .json .html .css \ No newline at end of file diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index c6ee9c92..ba380599 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -27,4 +27,7 @@ jobs: run: ruff format --check backend/ - name: Check linting with ruff - run: ruff check backend/ \ No newline at end of file + run: ruff check backend/ + + - name: Check for forbidden Unicode characters + run: bash backend/ci/forbidden-chars-check.sh backend/ docs/ --ext .py .rst \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py index 3860d5a5..c05bf4a1 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -26,7 +26,7 @@ # -- Project information ----------------------------------------------------- -# The documented project’s name +# The documented project's name project = src_project = PROJECT = "ibex" PACKAGE = "ibex" src_group = GROUP = "IMEX" diff --git a/docs/source/developers_manual/backend_development/backend_development_introduction.rst b/docs/source/developers_manual/backend_development/backend_development_introduction.rst index 233c3056..42039acb 100644 --- a/docs/source/developers_manual/backend_development/backend_development_introduction.rst +++ b/docs/source/developers_manual/backend_development/backend_development_introduction.rst @@ -9,9 +9,9 @@ Backend structure The IBEX backend is structured into three distinct layers, each represented by a corresponding directory within the ibex Python package: -* endpoints – Defines all HTTP API endpoints. This layer is strictly limited to request handling and routing, and does not contain any business logic. -* core – Serves as an abstraction layer between the endpoints and data_sources layers. Its primary role is to decouple application logic from specific data source implementations, enabling interchangeability. May include minimal logic when necessary. -* data_sources – Implements the core application logic. This layer is responsible for all communication with data sources (IMAS-Python) and constructs the JSON responses returned to frontend. +* endpoints - Defines all HTTP API endpoints. This layer is strictly limited to request handling and routing, and does not contain any business logic. +* core - Serves as an abstraction layer between the endpoints and data_sources layers. Its primary role is to decouple application logic from specific data source implementations, enabling interchangeability. May include minimal logic when necessary. +* data_sources - Implements the core application logic. This layer is responsible for all communication with data sources (IMAS-Python) and constructs the JSON responses returned to frontend. Endpoints discovering and testing ----------------------------------- diff --git a/docs/source/index.rst b/docs/source/index.rst index a8f7cfe9..601bbca2 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -7,7 +7,7 @@ Ibex Manual ============= IBEX is a web-based application designed for efficient traversal and visualization of data stored in the Integrated Data Structure (IDS). -The application follows a client–server architecture, consisting of a frontend for interactive data exploration and a backend responsible for +The application follows a client-server architecture, consisting of a frontend for interactive data exploration and a backend responsible for data processing and communication with data sources. The backend leverages the `IMAS Python `_ to access, parse, and manipulate IDS data, enabling seamless integration with existing IMAS-compatible databases. IBEX features a modular and extensible architecture, with the IMAS Python API encapsulated as a replaceable component, allowing it to be substituted with an alternative data access layer if needed. From 60cafdeda30740806a53e0cc205c1aca2df12011 Mon Sep 17 00:00:00 2001 From: wasikj Date: Mon, 22 Jun 2026 11:09:14 +0200 Subject: [PATCH 2/3] Rename script --- .github/workflows/frontend-linting.yml | 2 +- .github/workflows/linting.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/frontend-linting.yml b/.github/workflows/frontend-linting.yml index 4e03ed38..7d26ad3b 100644 --- a/.github/workflows/frontend-linting.yml +++ b/.github/workflows/frontend-linting.yml @@ -33,4 +33,4 @@ jobs: run: npm run lint - name: Check for forbidden Unicode characters - run: bash backend/ci/forbidden-chars-check.sh frontend/ --ext .ts .tsx .js .jsx .json .html .css \ No newline at end of file + run: bash backend/ci/forbidden_chars_check.sh frontend/ --ext .ts .tsx .js .jsx .json .html .css \ No newline at end of file diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index ba380599..6b228f01 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -30,4 +30,4 @@ jobs: run: ruff check backend/ - name: Check for forbidden Unicode characters - run: bash backend/ci/forbidden-chars-check.sh backend/ docs/ --ext .py .rst \ No newline at end of file + run: bash backend/ci/forbidden_chars_check.sh backend/ docs/ --ext .py .rst \ No newline at end of file From 41e91130df7b74cc8bce5d2796433450d474099c Mon Sep 17 00:00:00 2001 From: wasikj Date: Mon, 22 Jun 2026 14:06:24 +0200 Subject: [PATCH 3/3] Add missing script --- backend/ci/forbidden_chars_check.sh | 152 ++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100755 backend/ci/forbidden_chars_check.sh diff --git a/backend/ci/forbidden_chars_check.sh b/backend/ci/forbidden_chars_check.sh new file mode 100755 index 00000000..b6dd3a63 --- /dev/null +++ b/backend/ci/forbidden_chars_check.sh @@ -0,0 +1,152 @@ +#!/usr/bin/env bash +set -uo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +CHARS=( + $'\u2013' $'\u2014' $'\u2212' $'\u2018' $'\u2019' + $'\u201C' $'\u201D' $'\u2026' $'\u00A0' $'\u200B' + $'\u200C' $'\u200D' $'\u2060' $'\uFEFF' $'\u00AD' + $'\u2022' $'\u00D7' $'\u00F7' $'\u2190' $'\u2192' + $'\u21D2' $'\u2260' $'\u2264' $'\u2265' +) + +DESCS=( + "EN DASH (–)" + "EM DASH (—)" + "UNICODE MINUS (−)" + "LEFT SINGLE QUOTATION MARK (‘)" + "RIGHT SINGLE QUOTATION MARK (’)" + "LEFT DOUBLE QUOTATION MARK (“)" + "RIGHT DOUBLE QUOTATION MARK (”)" + "HORIZONTAL ELLIPSIS (…)" + "NON-BREAKING SPACE (NBSP)" + "ZERO WIDTH SPACE" + "ZERO WIDTH NON-JOINER" + "ZERO WIDTH JOINER" + "WORD JOINER" + "ZERO WIDTH NO-BREAK SPACE (BOM)" + "SOFT HYPHEN" + "BULLET (•)" + "MULTIPLICATION SIGN (×)" + "DIVISION SIGN (÷)" + "LEFT ARROW (←)" + "RIGHT ARROW (→)" + "RIGHTWARDS DOUBLE ARROW (⇒)" + "NOT EQUAL TO (≠)" + "LESS-THAN OR EQUAL TO (≤)" + "GREATER-THAN OR EQUAL TO (≥)" +) + +EXCLUDED_DIRS=( + __pycache__ .pytest_cache .mypy_cache .ruff_cache + .tox .venv venv ibex_venv imaspy_venv imas_core_develop_venv + build dist node_modules .git .webpack out ci generated _build +) + +DIRS=() +EXTS=() +AFTER_EXT=false + +for arg in "$@"; do + if [ "$arg" = "--help" ] || [ "$arg" = "-h" ]; then + echo "Usage: $(basename "$0") [directories...] [--ext extensions...]" + echo "" + echo "Scan source files for forbidden Unicode characters." + echo "" + echo "Arguments:" + echo " directories One or more directories to scan (default: ../ and ../../frontend)" + echo " --ext File extensions to check (default: all files)" + echo "" + echo "Examples:" + echo " $(basename "$0") Scan backend/ and frontend/" + echo " $(basename "$0") backend/ --ext .py Scan only .py files in backend/" + echo " $(basename "$0") frontend/ --ext .ts .tsx .js Scan only TS/JS files in frontend/" + echo " $(basename "$0") src/ docs/ --ext .py .md Scan custom dirs with custom extensions" + exit 0 + elif [ "$arg" = "--ext" ]; then + AFTER_EXT=true + elif [ "$AFTER_EXT" = true ]; then + EXTS+=("$arg") + else + DIRS+=("$arg") + fi +done + +# checks for forbidden chars in ../. (backend), ../../docs, and ../../frontend by default +# if no --ext given, all files are checked +if [ ${#DIRS[@]} -eq 0 ]; then + DIRS=("$SCRIPT_DIR/../" "$SCRIPT_DIR/../../docs" "$SCRIPT_DIR/../../frontend") +fi + +find_args=() + +for dir in "${DIRS[@]}"; do + if [ ! -d "$dir" ]; then + echo "Directory not found: $dir" >&2 + exit 1 + fi + + find_args+=("$(cd "$dir" && pwd)") +done + +find_args=("${find_args[@]}" -type f) + +if [ ${#EXTS[@]} -gt 0 ]; then + find_args+=("(") + find_args+=(-name "*${EXTS[0]}") + for ((i=1; i<${#EXTS[@]}; i++)); do + find_args+=(-o -name "*${EXTS[i]}") + done + find_args+=(")") +fi + +for d in "${EXCLUDED_DIRS[@]}"; do + find_args+=(! -path "*/$d/*") +done + +# Collect all matching files +all_files=() +while IFS= read -r -d '' file; do + all_files+=("$file") +done < <(find "${find_args[@]}" -print0 2>/dev/null) + +file_count=${#all_files[@]} + +if [ "$file_count" -eq 0 ]; then + echo "No files to check." + exit 0 +fi + +echo "Checking $file_count files..." + +errors=0 + +for ((i=0; i<${#CHARS[@]}; i++)); do + char="${CHARS[i]}" + desc="${DESCS[i]}" + + matches=$(printf '%s\0' "${all_files[@]}" | xargs -0 grep -In "$char" 2>/dev/null) || true + if [ -n "$matches" ]; then + while IFS= read -r grep_line; do + file="${grep_line%%:*}" + rest="${grep_line#*:}" + lineno="${rest%%:*}" + content="${rest#*:}" + + prefix="${content%%$char*}" + col=$(( ${#prefix} + 1 )) + + echo "$file:$lineno:$col: $desc" + done <<< "$matches" + ((errors++)) || true + fi +done + +if [ "$errors" -gt 0 ]; then + echo "" + echo "❌ Forbidden Unicode characters found in $errors file(s)." + exit 1 +fi + +echo "✅ No forbidden Unicode characters found."