Metadata-Version: 2.4
Name: dayamlchecker
Version: 1.5.0
Summary: An LSP for Docassemble YAML interviews
Author-email: Bryce Willey <bryce.steven.willey@gmail.com>, Quinten Steenhuis <qsteenhuis@suffolk.edu>
License-Expression: MIT
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: esprima>=4.0.1
Requires-Dist: mako>=1.3.10
Requires-Dist: black>=24.0.0
Requires-Dist: ruamel.yaml>=0.18.0
Requires-Dist: docx2python>=3.5.0
Requires-Dist: linkify-it-py>=2.0.3
Requires-Dist: pypdf>=5.0.0
Requires-Dist: requests>=2.31.0
Requires-Dist: urllib3>=2.0.0
Dynamic: license-file

# DAYamlChecker

An LSP for Docassemble YAML Interviews

## How to run

```bash
pip install .
python3 -m dayamlchecker `find . -name "*.yml" -path "*/questions/*" snot -path "*/.venv/*" -not -path "*/build/*"` # i.e. a space separated list of files
```

## Suppressing checks

You can suppress specific errors or warnings by their ID or finding class (`accessibility`, `style`, `translatability`, `general`). 

**Inline and block comments in YAML:**
To suppress a finding on a specific line, use a `# no-dayc: ` comment:
```yaml
question: Second  # no-dayc: EG101
```
To suppress findings for an entire document or block, use `# no-dayc-block: ` inside the block (e.g., after the `---` document marker):
```yaml
---
# no-dayc-block: style, WG123
code: |
  answer = 1
```
You can use `ALL` or `*` to suppress all findings on a line/block (`# no-dayc: ALL`). Multiple codes can be separated by spaces or commas.

**Command-line argument:**
To globally suppress findings across all files being checked, pass a comma-separated list of IDs or classes to the `--suppress` parameter:
```bash
python3 -m dayamlchecker --suppress accessibility,EG101 path/to/interview.yml
```

## WCAG checks

The checker includes WCAG-style checks for clear static accessibility failures in interview source. These checks run by default; use `--no-wcag` to disable them.

```bash
python3 -m dayamlchecker path/to/interview.yml          # WCAG checks on (default)
python3 -m dayamlchecker --no-wcag path/to/interview.yml  # WCAG checks off
python3 -m dayamlchecker --accessibility-error-on-widget combobox path/to/interview.yml  # opt into combobox failures
```

Some accessibility checks are behind runtime options while the rules are still being evaluated. Right now `combobox` failures are default-off and can be enabled with `--accessibility-error-on-widget combobox`.

## Style checks

Assembly Line style checks are opt-in. Enable them with `--style` to run
deterministic style and translatability findings ported from ALLinter without
duplicating the checker’s existing YAML, accessibility, or URL coverage.

Translatability findings have their own `translatability` finding class and
use `WT` warning codes. They include translated choice labels that lack
invariant stored values, user-facing strings embedded in code, and conditional
expressions or Mako blocks that change only part of a sentence.

```bash
python3 -m dayamlchecker --style --no-url-check path/to/interview.yml
python3 -m dayamlchecker --style-llm --openai-api-key "$OPENAI_API_KEY" path/to/interview.yml
OPENAI_BASE_URL=https://api.openai.com/v1 OPENAI_API_KEY=... python3 -m dayamlchecker --style-llm path/to/interview.yml
```

`--style-llm` also enables `--style`. It reads `OPENAI_BASE_URL`, `OPENAI_API_KEY`, and `OPENAI_MODEL` from the environment when flags are not provided. The checker only emits sanitized configuration/request errors for LLM-backed style rules and does not print the credential values.

For Python callers, use the module helper instead of shelling out:

```python
from dayamlchecker import RuntimeOptions, find_style_findings_from_string

findings = find_style_findings_from_string(
    interview_yaml,
    input_file="interview.yml",
    runtime_options=RuntimeOptions(style_include_llm=True),
)
```

## URL checks

The main `dayamlchecker` CLI also runs the URL checker by default. Broken URLs in question files fail the command; broken URLs in related `data/templates` files are warnings by default. Use `--no-url-check` to skip it, or tune it with flags such as `--url-check-timeout`, `--url-check-ignore-urls`, `--url-check-skip-templates`, `--template-url-severity`, and `--unreachable-url-severity`.

Current accessibility checks focus on objective failures only:

- Missing alt text in markdown images
- Missing alt text in Docassemble `[FILE ...]` image tags
- Missing alt text in HTML `<img>` tags
- Skipped markdown heading levels such as `##` to `####`
- Skipped HTML heading levels such as `<h2>` to `<h4>`
- Empty link text
- Non-descriptive link text such as `click here`, `here`, `read more`, and Spanish equivalents like `haga clic aquí`
- `no label` and empty/missing labels on multi-field screens (allowed on single-field screens)
- Low contrast in custom Bootstrap theme CSS loaded by `features: bootstrap theme`; inspects actual CSS values for body text, navbar, dropdown menu, and buttons (minimum ratio 4.5:1)
- Templates used with `display_template()` that have a missing or empty `subject`

Optional runtime-gated accessibility checks:

- `combobox` usage, including `datatype: combobox` when `--accessibility-error-on-widget combobox` is enabled

Accessibility informational notes are also emitted for likely PDF accessibility issues:

- DOCX attachments missing `tagged pdf: True` (set this in `features` or on the attachment)

WCAG checks still report YAML parse errors, so CI/CD can surface broken YAML and accessibility failures in one run.

This mode is source-based static analysis. It does not audit rendered pages for runtime behavior or JavaScript-created accessibility issues.

## DOCX template checks

Any `.docx` files you pass on the command line are checked for static
accessibility problems in the documents users receive: missing alt text,
empty or ambiguous link text, missing language metadata, heading structure,
table header and merged-cell risks, explicitly low-contrast text, and
floating objects or text boxes that disturb reading order. These run by
default; use `--no-docx-accessibility` to skip them.

**Every finding is capped at warning severity by default**, so turning these
checks on reports problems without failing the build. Most existing
templates have findings today, and the intent is for authors to work through
them over time rather than to block a release. Opt into failing with
`--docx-accessibility-severity error`, which restores each rule's own
severity.

```bash
# Report findings without failing (the default)
python3 -m dayamlchecker docassemble/MyPackage/data/templates

# Fail the command when a document has accessibility errors
python3 -m dayamlchecker --docx-accessibility-severity error docassemble/MyPackage/data/templates
```

DOCX findings use the same diagnostic codes, `--suppress`, `--format github`
and `--max-warnings` machinery as every other check. They are numbered
`EA540`-`IA567` in the accessibility range, so a single noisy rule is
silenced the usual way:

```bash
python3 -m dayamlchecker --suppress IA561 ...   # missing document title
```

Because a DOCX has no line numbers, findings name the package part they came
from (`word/document.xml`, `word/header1.xml`) and quote up to 80 characters
of nearby text so you can search the document for the problem:

```
WARN  [WA552] docassemble/MyPackage/data/templates/discovery.docx
  a table in word/document.xml has no obvious header row marker
  (table begins "Certificate of Service")
IA565  the document contains 48 empty paragraphs used for spacing, the
  longest run being 7 (longest run is near "v.")
```

Tables quote their first text, images and text boxes quote the paragraph
beside them, and empty-paragraph runs quote what precedes them. Findings that
would otherwise read identically are kept separate, so two tables with the
same problem are two findings rather than one.
