diff options
| author | Nikita Shubin <nikita.shubin@maquefel.me> | 2026-05-17 12:24:14 +0300 |
|---|---|---|
| committer | Nikita Shubin <nikita.shubin@maquefel.me> | 2026-05-17 12:24:14 +0300 |
| commit | 8ce0605c7e197b4746eb8d8a8d70fa20cea789b3 (patch) | |
| tree | 965dd29d52098994af378abf1832f55c2f9fe38b | |
| parent | c6a6697a89a4d9e6d837946a46f534da941db6d5 (diff) | |
| download | landau.one-8ce0605c7e197b4746eb8d8a8d70fa20cea789b3.tar.gz landau.one-8ce0605c7e197b4746eb8d8a8d70fa20cea789b3.zip | |
scripts: Add hunspell checker
See original commit by Viacheslav Bocharov <v@baodeep.com>
https://github.com/adeepn/landau/commit/c694f9d9f41d0b5298fc822edcdfba61bceadb6c.
[Splitted checker into content repo site]
Signed-off-by: Nikita Shubin <nikita.shubin@maquefel.me>
| -rw-r--r-- | .spellcheck-allow.txt | 89 | ||||
| -rwxr-xr-x | scripts/spellcheck.sh | 112 |
2 files changed, 201 insertions, 0 deletions
diff --git a/.spellcheck-allow.txt b/.spellcheck-allow.txt new file mode 100644 index 0000000..a14a49d --- /dev/null +++ b/.spellcheck-allow.txt @@ -0,0 +1,89 @@ +AOSP +BSP +CalVer +Dependabot +LTS +Lightbox +ODM +OSDevConf +OpenHands +PEM +PRs +RGB +RSS +RULKC +SCSS +SHA +UI +YAML +backlink +canonicalise +changelog +codespell +cron +dirs +docroot +env +favicon +flavoured +frontmatter +github +hostname +hunspell +inlined +labelled +linux +mailto +md +nginx +og +params +px +repo +roadmap +rsync +rsyncing +rsyncs +rulkc +submodule +toolchain +url +апстрим +Митапы +Форк +агенда +архитектур +бэк +валидируемый +валидны +вендоров +деплой +десктопов +драфты +коммит +коммитит +коммиты +конфиге +мейнтейнеров +мерж +мержа +митапы +патчей +перебилдит +перевыпустили +перегенерировать +прогонятся +продакшн +продакшне +пуше +пушем +разрулит +ревью +репозитории +репозитория +санкционные +удвоений +форк +форка +форке +форки diff --git a/scripts/spellcheck.sh b/scripts/spellcheck.sh new file mode 100755 index 0000000..caf08f4 --- /dev/null +++ b/scripts/spellcheck.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash +# Spell-check Markdown sources using hunspell with ru_RU + en_US dictionaries. +# Words listed in .spellcheck-allow.txt are accepted as correct. +# +# Usage: scripts/spellcheck.sh [paths...] +# Default scope when no args given: content/, docs/, README.md, AGENTS.md. + +set -euo pipefail + +ROOT=$(cd "$(dirname "$0")/.." && pwd) +ALLOW="${ROOT}/.spellcheck-allow.txt" +[ -f "${ALLOW}" ] || { echo "missing allow list: ${ALLOW}" >&2; exit 1; } + +cd "${ROOT}" + +PATHS=("$@") +if [ "${#PATHS[@]}" -eq 0 ]; then + PATHS=(content docs README.md AGENTS.md) +fi + +# Build the file list. Avoid `mapfile`/`readarray` so the script runs on +# Bash 3.2 (macOS default) as well as Linux's modern bash. +files=() +while IFS= read -r line; do + [ -n "${line}" ] && files+=("${line}") +done < <( + for p in "${PATHS[@]}"; do + [ -e "${p}" ] || continue + if [ -d "${p}" ]; then + find "${p}" -type f -name '*.md' + else + printf '%s\n' "${p}" + fi + done | sort -u +) + +if [ "${#files[@]}" -eq 0 ]; then + echo "no markdown files found" + exit 0 +fi + +# Sanity check: confirm hunspell can actually load both dictionaries. +# (On some environments — e.g. GitHub Actions ubuntu-24.04 runner image — +# Ubuntu's hunspell-ru / hunspell-en-us packages can install successfully +# but leave /usr/share/hunspell/ stripped of the .aff/.dic files. Set +# DICPATH to a directory containing ru_RU.{aff,dic} and en_US.{aff,dic} as +# a workaround.) +if echo 'архитектура' | hunspell -d ru_RU,en_US -l | grep -qx 'архитектура'; then + echo "::error::hunspell ru_RU dictionary not loaded properly" + echo "DICPATH=${DICPATH:-(unset)}" + hunspell -D 2>&1 | head -30 + exit 1 +fi +if echo 'architecture' | hunspell -d ru_RU,en_US -l | grep -qx 'architecture'; then + echo "::error::hunspell en_US dictionary not loaded properly" + echo "DICPATH=${DICPATH:-(unset)}" + hunspell -D 2>&1 | head -30 + exit 1 +fi + +# Explicit template — bare `mktemp` errors on macOS/BSD (`too few X's in template`). +unknown=$(mktemp "${TMPDIR:-/tmp}/landau-spellcheck.XXXXXX") +trap 'rm -f "${unknown}"' EXIT + +for f in "${files[@]}"; do + awk ' + BEGIN { fm = 0; code = 0 } + NR == 1 && /^---[[:space:]]*$/ { fm = 1; next } + fm && /^---[[:space:]]*$/ { fm = 0; next } + fm { next } + /^[[:space:]]*```/ { code = !code; next } + code { next } + { + gsub(/<[^>]*>/, " ") # HTML tags + gsub(/`[^`]*`/, " ") # inline code spans + gsub(/https?:\/\/[^[:space:])]+/, " ") # URLs + gsub(/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+/, " ") # emails + gsub(/[][(){}|*_~#]/, " ") # markdown punctuation + # Strip invisible Unicode chars that confuse hunspell tokenizer. + # Byte sequences below are the UTF-8 encodings of: + gsub(/\xef\xb8\x8f/, " ") # U+FE0F variation selector-16 + gsub(/\xef\xb8\x8e/, " ") # U+FE0E variation selector-15 + gsub(/\xe2\x80\x8d/, " ") # U+200D zero-width joiner + gsub(/\xe2\x80\x8c/, " ") # U+200C zero-width non-joiner + gsub(/\xe2\x80\x8b/, " ") # U+200B zero-width space + print + } + ' "$f" \ + | hunspell -d ru_RU,en_US -l \ + >> "${unknown}" +done + +# Empty unknown list = nothing to filter; happy exit. +if [ ! -s "${unknown}" ]; then + echo "Spell check OK across ${#files[@]} files." + exit 0 +fi + +# Filter accumulated unknowns against the allow list (exact, fixed strings). +sort -u "${unknown}" -o "${unknown}" +filtered=$(grep -vxFf "${ALLOW}" "${unknown}" || true) + +if [ -n "${filtered}" ]; then + echo "::error::Unknown words found in markdown sources:" + printf '%s\n' "${filtered}" | sed 's/^/ /' + echo + echo "If these are intentional (proper nouns, technical terms)," + echo "add them to .spellcheck-allow.txt. Otherwise, fix the spelling." + exit 1 +fi + +echo "Spell check OK across ${#files[@]} files." |
