lint_jsonhtl.py

Command-line tool to lint JSONHTL documents. Takes one or more URLs (file://, http://, https://), fetches each, and runs jsonhtl_lint.validate() on the result. Lives at ~/lint_jsonhtl.py on the DAP AWS instance.

Note: the spec in gdata-server/linter describes a future CLI with --key, --file, --all, and --schema flags. The current implementation uses positional URL arguments instead. This is a known gap -- see Future Improvements in the spec.

Usage

# Lint a local JSON file
python lint_jsonhtl.py file:///home/john/tmp/doc.json

# Lint multiple files
python lint_jsonhtl.py file:///path/a.json file:///path/b.json

# Lint via HTTP (requires notes API to serve raw JSON)
python lint_jsonhtl.py http://127.0.0.1:8020/some/key

# Exit code: 0 if all clean, 1 if any issues found

Code

#!/usr/bin/env python3
"""
lint_jsonhtl.py -- JSONHTL document linter (CLI).

Usage:
    python lint_jsonhtl.py <url> [url ...]

Each url may be file://, http://, or https://.
Fetches and validates each document. Prints issues to stdout.
Exit code: 0 if all clean, 1 if any issues found.

The validator lives in jsonhtl_lint.py (separate module, reusable elsewhere).
"""

import json
import sys
import urllib.request
from jsonhtl_lint import validate


def fetch(url):
    with urllib.request.urlopen(url) as r:
        return json.loads(r.read())


def main():
    urls = sys.argv[1:]
    if not urls:
        print(f"Usage: {sys.argv[0]} <url> [url ...]", file=sys.stderr)
        print("  url may be file://, http://, or https://", file=sys.stderr)
        sys.exit(1)

    any_errors = False
    for url in urls:
        print(f"--- {url}")
        try:
            doc = fetch(url)
        except Exception as e:
            print(f"  FETCH ERROR: {e}")
            any_errors = True
            continue

        issues = validate(doc)
        if issues:
            any_errors = True
            for issue in issues:
                print(f"  {issue}")
        else:
            print("  OK")

    sys.exit(1 if any_errors else 0)


if __name__ == "__main__":
    main()
version 1  ·  updated 2026-07-06