linkml-reference-validator 0.2.1rc2__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/PKG-INFO +2 -2
- linkml_reference_validator-0.3.0/docs/assets/zotero-find-full-text.png +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/concepts/editorial-conventions.md +9 -4
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/concepts/how-it-works.md +45 -0
- linkml_reference_validator-0.3.0/docs/how-to/export-cache-to-zotero.md +114 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/how-to/fetch-full-text-and-pdfs.md +145 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/how-to/repair-validation-errors.md +43 -1
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/how-to/use-local-files-and-urls.md +2 -2
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/how-to/validate-clinical-trials.md +4 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/how-to/validate-urls.md +47 -15
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/reference/cli.md +144 -24
- linkml_reference_validator-0.3.0/docs/reference/splitting.md +69 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/setup-guide.md +4 -0
- linkml_reference_validator-0.3.0/docs/superpowers/plans/2026-08-05-private-library-full-text.md +190 -0
- linkml_reference_validator-0.3.0/docs/superpowers/specs/2026-08-05-private-library-full-text-design.md +309 -0
- linkml_reference_validator-0.3.0/docs/troubleshooting.md +986 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/tutorials/complete-workflow.md +1 -1
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/mkdocs.yml +2 -0
- linkml_reference_validator-0.3.0/src/linkml_reference_validator/cli/cache.py +410 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/cli/lookup.py +3 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/cli/repair.py +66 -12
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/cli/validate.py +53 -21
- linkml_reference_validator-0.3.0/src/linkml_reference_validator/etl/__init__.py +12 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/acquire.py +80 -1
- linkml_reference_validator-0.3.0/src/linkml_reference_validator/etl/csl_export.py +73 -0
- linkml_reference_validator-0.3.0/src/linkml_reference_validator/etl/extract/__init__.py +31 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/extract/base.py +11 -3
- linkml_reference_validator-0.3.0/src/linkml_reference_validator/etl/extract/html.py +287 -0
- linkml_reference_validator-0.3.0/src/linkml_reference_validator/etl/extract/pdf.py +136 -0
- linkml_reference_validator-0.3.0/src/linkml_reference_validator/etl/extract/xml.py +253 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/fulltext/__init__.py +2 -0
- linkml_reference_validator-0.3.0/src/linkml_reference_validator/etl/fulltext/base.py +200 -0
- linkml_reference_validator-0.3.0/src/linkml_reference_validator/etl/fulltext/openalex.py +106 -0
- linkml_reference_validator-0.3.0/src/linkml_reference_validator/etl/fulltext/pmc.py +198 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/fulltext/unpaywall.py +25 -9
- linkml_reference_validator-0.3.0/src/linkml_reference_validator/etl/fulltext/zotero.py +252 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/identifiers.py +19 -0
- linkml_reference_validator-0.3.0/src/linkml_reference_validator/etl/reference_fetcher.py +1941 -0
- linkml_reference_validator-0.3.0/src/linkml_reference_validator/etl/rules.py +195 -0
- linkml_reference_validator-0.3.0/src/linkml_reference_validator/etl/sources/pmid.py +594 -0
- linkml_reference_validator-0.3.0/src/linkml_reference_validator/etl/sources/url.py +273 -0
- linkml_reference_validator-0.3.0/src/linkml_reference_validator/matching.py +75 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/models.py +149 -18
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/plugins/reference_validation_plugin.py +50 -1
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/validation/repairer.py +83 -1
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/validation/supporting_text_validator.py +191 -21
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/fixtures/GEO_GSE12345.md +1 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/fixtures/PMC_TEST001.md +1 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/fixtures/PMC_TEST002.md +2 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/fixtures/PMID_TEST001.md +1 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/fixtures/PMID_TEST002.md +1 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/fixtures/PMID_TEST003.md +2 -0
- linkml_reference_validator-0.2.1rc2/tests/fixtures/CLINICALTRIALS_NCT00000001.md → linkml_reference_validator-0.3.0/tests/fixtures/clinicaltrials_NCT00000001.md +1 -0
- linkml_reference_validator-0.3.0/tests/fixtures/fulltext_html/README.md +22 -0
- linkml_reference_validator-0.3.0/tests/fixtures/fulltext_html/dspace-32894695.html +1 -0
- linkml_reference_validator-0.3.0/tests/fixtures/fulltext_html/iris-19049553.html +359 -0
- linkml_reference_validator-0.3.0/tests/fixtures/fulltext_html/plos-0000308.html +78 -0
- linkml_reference_validator-0.3.0/tests/fixtures/jats/PMC5593426.xml +5 -0
- linkml_reference_validator-0.3.0/tests/fixtures/jats/README.md +21 -0
- linkml_reference_validator-0.3.0/tests/test_absent_abstract_recovery.py +140 -0
- linkml_reference_validator-0.3.0/tests/test_acquire.py +224 -0
- linkml_reference_validator-0.3.0/tests/test_cache_author_recovery.py +102 -0
- linkml_reference_validator-0.3.0/tests/test_cli_cache_enrich.py +227 -0
- linkml_reference_validator-0.3.0/tests/test_cli_cache_export.py +246 -0
- linkml_reference_validator-0.3.0/tests/test_cli_cache_reference.py +271 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_cli_repair.py +134 -0
- linkml_reference_validator-0.3.0/tests/test_clinicaltrials_cache.py +234 -0
- linkml_reference_validator-0.3.0/tests/test_empty_snippets.py +794 -0
- linkml_reference_validator-0.3.0/tests/test_extractor_fidelity.py +656 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_extractors.py +13 -0
- linkml_reference_validator-0.3.0/tests/test_frontmatter_and_doi_case.py +334 -0
- linkml_reference_validator-0.3.0/tests/test_fulltext_providers.py +356 -0
- linkml_reference_validator-0.3.0/tests/test_html_fulltext_acceptance.py +432 -0
- linkml_reference_validator-0.3.0/tests/test_jats_tables.py +346 -0
- linkml_reference_validator-0.3.0/tests/test_ligature_normalization.py +91 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_models.py +13 -0
- linkml_reference_validator-0.3.0/tests/test_no_cache_downgrade.py +540 -0
- linkml_reference_validator-0.3.0/tests/test_open_access_policy.py +686 -0
- linkml_reference_validator-0.3.0/tests/test_pdf_url_title.py +228 -0
- linkml_reference_validator-0.3.0/tests/test_pmid_network.py +327 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_reference_fetcher.py +700 -3
- linkml_reference_validator-0.3.0/tests/test_rules.py +129 -0
- linkml_reference_validator-0.3.0/tests/test_serve_stale_html_optin.py +134 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_sources.py +300 -0
- linkml_reference_validator-0.3.0/tests/test_split_supporting_text.py +75 -0
- linkml_reference_validator-0.3.0/tests/test_trust_cached_entries.py +81 -0
- linkml_reference_validator-0.3.0/tests/test_url_html_sanitize.py +161 -0
- linkml_reference_validator-0.3.0/tests/test_url_source_cache_version.py +141 -0
- linkml_reference_validator-0.3.0/tests/test_validation_counts.py +407 -0
- linkml_reference_validator-0.3.0/tests/test_zotero_provider.py +277 -0
- linkml_reference_validator-0.2.1rc2/docs/troubleshooting.md +0 -706
- linkml_reference_validator-0.2.1rc2/src/linkml_reference_validator/cli/cache.py +0 -143
- linkml_reference_validator-0.2.1rc2/src/linkml_reference_validator/etl/__init__.py +0 -9
- linkml_reference_validator-0.2.1rc2/src/linkml_reference_validator/etl/extract/__init__.py +0 -16
- linkml_reference_validator-0.2.1rc2/src/linkml_reference_validator/etl/extract/html.py +0 -46
- linkml_reference_validator-0.2.1rc2/src/linkml_reference_validator/etl/extract/pdf.py +0 -67
- linkml_reference_validator-0.2.1rc2/src/linkml_reference_validator/etl/extract/xml.py +0 -46
- linkml_reference_validator-0.2.1rc2/src/linkml_reference_validator/etl/fulltext/base.py +0 -70
- linkml_reference_validator-0.2.1rc2/src/linkml_reference_validator/etl/fulltext/openalex.py +0 -70
- linkml_reference_validator-0.2.1rc2/src/linkml_reference_validator/etl/fulltext/pmc.py +0 -124
- linkml_reference_validator-0.2.1rc2/src/linkml_reference_validator/etl/reference_fetcher.py +0 -786
- linkml_reference_validator-0.2.1rc2/src/linkml_reference_validator/etl/sources/pmid.py +0 -390
- linkml_reference_validator-0.2.1rc2/src/linkml_reference_validator/etl/sources/url.py +0 -148
- linkml_reference_validator-0.2.1rc2/tests/test_acquire.py +0 -116
- linkml_reference_validator-0.2.1rc2/tests/test_fulltext_providers.py +0 -175
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.claude/.mcp.json +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.claude/settings.json +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.copier-answers.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.devcontainer/devcontainer.json +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.devcontainer/post_create.sh +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.editorconfig +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.github/actions/claude-code-action/action.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.github/actions/claude-issue-summarize-action/action.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.github/actions/claude-issue-triage-action/action.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.github/ai-controllers.json +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.github/copilot-instructions.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.github/copilot-setup-steps.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.github/dependabot.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.github/workflows/claude-code-review.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.github/workflows/claude-issue-summarize.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.github/workflows/claude-issue-triage.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.github/workflows/claude-ontology-review.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.github/workflows/claude.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.github/workflows/deploy-docs.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.github/workflows/dragon-ai.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.github/workflows/main.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.github/workflows/pypi-publish.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.gitignore +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.goosehints +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.pre-commit-config.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/.yamllint.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/AGENTS.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/BUG_GEO_ACCESSION_TO_UID.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/BUG_ZENODO_DOI_AND_URL_HANDLING.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/CLAUDE.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/CLI-ISSUES.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/CODE_OF_CONDUCT.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/CONTRIBUTING.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/FEATURE_REQUEST_REPAIR.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/LICENSE +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/README.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/REVIEW2.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/REVIEW3.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/ai.just +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/copilot-instructions.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/about.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/concepts/content-types.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/elements/.gitkeep +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/how-to/add-reference-source.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/how-to/skip-unsupported-references.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/how-to/validate-dois.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/how-to/validate-entrez.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/how-to/validate-obo-files.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/how-to/validate-titles.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/index.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/notebooks/01_getting_started.ipynb +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/notebooks/02_advanced_usage.ipynb +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/notebooks/03_python_api.ipynb +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/notebooks/04_obo_validation.ipynb +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/notebooks/05_geo_validation.ipynb +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/quickstart.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/superpowers/plans/2026-06-12-modular-pdf-fulltext-fetching.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/superpowers/specs/2026-06-12-modular-pdf-fulltext-fetching-design.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/templates-linkml/README.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/docs/todo.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/examples/README.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/justfile +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/mypy.ini +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/notebooks/01_getting_started.ipynb +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/notebooks/02_advanced_usage.ipynb +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/notebooks/03_python_api.ipynb +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/notebooks/README.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/project/README.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/project.justfile +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/pyproject.toml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/pytest.ini +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/__init__.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/_version.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/cli/__init__.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/cli/shared.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/fulltext/epmc_preprint.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/fulltext/json_api.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/fulltext/loader.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/sources/__init__.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/sources/base.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/sources/clinicaltrials.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/sources/doi.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/sources/entrez.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/sources/file.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/sources/json_api.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/sources/loader.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/sources/ppr.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/sources/utils.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/etl/text_extractor.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/field_detection.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/plugins/REVIEW.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/plugins/__init__.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/validation/__init__.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/src/linkml_reference_validator/validation/fuzzy_text_utils.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/__init__.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/conftest.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/data/test_data_deep_nesting_invalid.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/data/test_data_deep_nesting_valid.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/data/test_data_invalid.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/data/test_data_valid.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/data/test_schema.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/data/test_schema_deep_nesting.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/fixtures/PMC_TEST001.txt +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/fixtures/PMC_TEST002.txt +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/fixtures/PMID_TEST001.txt +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/fixtures/PMID_TEST002.txt +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/fixtures/PMID_TEST003.txt +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/fixtures/sample.obo +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_cli.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_cli_lookup.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_clinicaltrials_integration.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_deep_nesting.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_doi_preprint.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_e2e_integration.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_epmc_preprint_provider.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_field_detection.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_fulltext_loader.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_fuzzy_suggestions.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_geo_integration.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_identifiers.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_json_api_source.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_optional_linkml_dependency.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_plugin_integration.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_pmc_fulltext.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_ppr_source.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_real_validation.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_repair.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_source_utils.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_supporting_text_validator.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_text_extractor.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_title_validation.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_unknown_slot_traversal.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/tests/test_validation_config.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.3.0}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: linkml_reference_validator
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Validation of supporting text from references and publications
|
|
5
5
|
Author-email: Chris Mungall <cjmungall@lbl.gov>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
Binary file
|
|
@@ -248,7 +248,7 @@ Editorial conventions work the same in data files:
|
|
|
248
248
|
|
|
249
249
|
### Normalization Order
|
|
250
250
|
|
|
251
|
-
1. Remove
|
|
251
|
+
1. Remove editorial `[...]` content unless a configured literal pattern matches
|
|
252
252
|
2. Split on `...` if present
|
|
253
253
|
3. For each part:
|
|
254
254
|
- Lowercase
|
|
@@ -258,10 +258,15 @@ Editorial conventions work the same in data files:
|
|
|
258
258
|
|
|
259
259
|
### Regular Expressions
|
|
260
260
|
|
|
261
|
-
Brackets: `\[
|
|
262
|
-
Ellipsis: `\.\.\.` (splits on three dots exactly)
|
|
261
|
+
Brackets: `\[.*?\]` (single-line, non-nested matching; literal patterns can preserve matches)
|
|
263
262
|
|
|
264
|
-
|
|
263
|
+
Ellipsis: `\s*\.{2,}\s*` (splits on two or more ASCII periods)
|
|
264
|
+
|
|
265
|
+
Both `..` (two dots) and `....` (four dots) are treated as separators. The Unicode
|
|
266
|
+
ellipsis `…` is not a separator.
|
|
267
|
+
|
|
268
|
+
Python callers can use the public [supporting text splitting helper](../reference/splitting.md)
|
|
269
|
+
without constructing a validator.
|
|
265
270
|
|
|
266
271
|
## See Also
|
|
267
272
|
|
|
@@ -36,6 +36,51 @@ reference_content = "...The MUC1 oncoprotein blocks nuclear..."
|
|
|
36
36
|
# Match: "muc1 oncoprotein" found in normalized reference
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
**Empty excerpts are rejected:**
|
|
40
|
+
|
|
41
|
+
An empty or whitespace-only excerpt is always an error, never a pass. The
|
|
42
|
+
empty string is a substring of every document, so a blank excerpt would
|
|
43
|
+
otherwise be reported as verified evidence while quoting nothing at all:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
supporting_text = "" # or " ", "\n"
|
|
47
|
+
# ERROR: Supporting text is empty
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The check runs before the reference is fetched, and applies even when the
|
|
51
|
+
reference prefix is on the [skip list](../how-to/skip-unsupported-references.md):
|
|
52
|
+
a blank excerpt is a defect in the data regardless of what it cites. An
|
|
53
|
+
excerpt slot that is *absent* is a different matter — whether it is required
|
|
54
|
+
is up to your schema.
|
|
55
|
+
|
|
56
|
+
**Minimum excerpt length (optional):**
|
|
57
|
+
|
|
58
|
+
A blank excerpt is the extreme case. A two-character one is barely better: a
|
|
59
|
+
short string matches almost any paper by chance, so the match succeeds without
|
|
60
|
+
the excerpt being real evidence. Set `min_excerpt_length` to require a minimum:
|
|
61
|
+
|
|
62
|
+
```yaml
|
|
63
|
+
# .linkml-reference-validator.yaml
|
|
64
|
+
validation:
|
|
65
|
+
min_excerpt_length: 20
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Keep it under `validation:`. A config file that has a `validation:` section
|
|
69
|
+
ignores validation keys placed at the top level — silently, which for an
|
|
70
|
+
opt-in check means it looks enabled while never running.
|
|
71
|
+
|
|
72
|
+
The check is off by default (`0`), so existing data keeps validating as before.
|
|
73
|
+
Length is measured in **non-whitespace characters of quoted text**:
|
|
74
|
+
|
|
75
|
+
- Whitespace is ignored, so PDF-to-text extraction damage does not change the
|
|
76
|
+
count — `"t he pro tein"` and `"the protein"` both measure 10.
|
|
77
|
+
- No tokenizing, so chemical nomenclature and other punctuation-dense strings
|
|
78
|
+
are counted in full — `"2,3-dihydroxybenzoate"` measures 21, not 2 words.
|
|
79
|
+
- Editorial `[brackets]` and `...` separators do not count, since they are
|
|
80
|
+
never matched against the reference.
|
|
81
|
+
|
|
82
|
+
Like the blank check, this runs before the reference is fetched.
|
|
83
|
+
|
|
39
84
|
### 3. Ellipsis Handling
|
|
40
85
|
|
|
41
86
|
When supporting text contains `...`, each part is matched separately:
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Export a Reference Cache to Zotero
|
|
2
|
+
|
|
3
|
+
This workflow turns a checked-in public reference cache into a Zotero collection,
|
|
4
|
+
asks Zotero to find available PDFs, and then inventories the resulting attachments
|
|
5
|
+
without putting closed manuscripts into the project repository.
|
|
6
|
+
|
|
7
|
+
The three stores remain separate:
|
|
8
|
+
|
|
9
|
+
| Store | Purpose | Safe to commit? |
|
|
10
|
+
|---|---|---:|
|
|
11
|
+
| Project `references_cache` | Reproducible public validation evidence | Yes |
|
|
12
|
+
| Zotero library | User-managed references and PDF attachments | No |
|
|
13
|
+
| Private research cache | Extracted user-library text for agent context | No |
|
|
14
|
+
|
|
15
|
+
Normal validation reads only the first store.
|
|
16
|
+
|
|
17
|
+
## 1. Export metadata from the public cache
|
|
18
|
+
|
|
19
|
+
Run the exporter from the `linkml-reference-validator` checkout. For dismech:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
uv run linkml-reference-validator cache export \
|
|
23
|
+
--cache-dir /Users/cjm/repos/dismech/references_cache \
|
|
24
|
+
--needs-full-text \
|
|
25
|
+
--output /Users/cjm/Downloads/dismech-zotero.json
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`--needs-full-text` is the default. It excludes cache entries that already have
|
|
29
|
+
full text, excludes non-publication identifiers, and deduplicates by normalized
|
|
30
|
+
DOI and then PMID. The CSL JSON output uses an explicit metadata allowlist:
|
|
31
|
+
|
|
32
|
+
- title and authors;
|
|
33
|
+
- journal and year;
|
|
34
|
+
- DOI; or
|
|
35
|
+
- PMID and its public PubMed URL.
|
|
36
|
+
|
|
37
|
+
It never contains cached article text, excerpts, provenance, PDFs, local paths,
|
|
38
|
+
or private-cache data. The command refuses to replace an existing output file;
|
|
39
|
+
use `--force` only after checking the destination. Use `--all` if you explicitly
|
|
40
|
+
want eligible references that already contain full text.
|
|
41
|
+
|
|
42
|
+
## 2. Import the file into Zotero
|
|
43
|
+
|
|
44
|
+
In Zotero:
|
|
45
|
+
|
|
46
|
+
1. Choose **File → Import**.
|
|
47
|
+
2. Choose **A file**.
|
|
48
|
+
3. Select `dismech-zotero.json`.
|
|
49
|
+
4. Keep the imported records in a project-specific collection such as
|
|
50
|
+
**dismech**.
|
|
51
|
+
|
|
52
|
+
CSL JSON is a standard format supported by Zotero. Importing the file adds only
|
|
53
|
+
bibliographic records; it does not copy anything from the validator's caches.
|
|
54
|
+
|
|
55
|
+
## 3. Ask Zotero to find PDFs
|
|
56
|
+
|
|
57
|
+
Select one or more top-level journal articles in the center item list,
|
|
58
|
+
right-click the selection, and choose **Find Full Text**. It is a built-in Zotero
|
|
59
|
+
command, not a plugin.
|
|
60
|
+
|
|
61
|
+

|
|
62
|
+
|
|
63
|
+
The command appears for an eligible parent item that has a DOI and does not
|
|
64
|
+
already have a file attachment. It may also be unavailable in a group library
|
|
65
|
+
where files cannot be added. If it is absent, first test a single article in
|
|
66
|
+
your personal library and confirm that its DOI field is populated.
|
|
67
|
+
|
|
68
|
+
For a large import, start with a modest batch rather than all records at once.
|
|
69
|
+
Publishers can temporarily rate-limit repeated requests, and a later retry may
|
|
70
|
+
find additional files. Zotero reports **Full Text PDF** or **No file found** for
|
|
71
|
+
each attempted item.
|
|
72
|
+
|
|
73
|
+
## 4. Inventory the enriched Zotero library
|
|
74
|
+
|
|
75
|
+
Once Zotero finishes, scan the project cache again:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
uv run linkml-reference-validator cache enrich \
|
|
79
|
+
--provider zotero \
|
|
80
|
+
--cache-dir /Users/cjm/repos/dismech/references_cache \
|
|
81
|
+
--dry-run
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
This read-only scan matches exact DOI, PMID, or PMCID identifiers and reports
|
|
85
|
+
which cached references now have usable Zotero text or PDF attachments. It does
|
|
86
|
+
not invoke **Find Full Text** and does not modify Zotero.
|
|
87
|
+
|
|
88
|
+
After reviewing the matches, materialize them into the separate private research
|
|
89
|
+
cache:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
uv run linkml-reference-validator cache enrich \
|
|
93
|
+
--provider zotero \
|
|
94
|
+
--cache-dir /Users/cjm/repos/dismech/references_cache \
|
|
95
|
+
--apply
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Apply mode leaves `references_cache` unchanged. Private content goes to
|
|
99
|
+
`~/.cache/linkml-reference-validator/private` by default with owner-only
|
|
100
|
+
permissions. Agents may inspect it for context, but validation cannot use it as
|
|
101
|
+
evidence.
|
|
102
|
+
|
|
103
|
+
## 5. Validate reproducibly
|
|
104
|
+
|
|
105
|
+
Run validation normally. Results remain reproducible because the validator
|
|
106
|
+
reads the public project cache and accepts only public full-text provider results.
|
|
107
|
+
Neither the contents of Zotero nor the machine-specific private cache affect
|
|
108
|
+
validation.
|
|
109
|
+
|
|
110
|
+
## See also
|
|
111
|
+
|
|
112
|
+
- [Fetching Full Text and PDFs](fetch-full-text-and-pdfs.md)
|
|
113
|
+
- [Zotero: importing standardized formats](https://www.zotero.org/support/kb/importing_standardized_formats)
|
|
114
|
+
- [Zotero: adding files to a library](https://www.zotero.org/support/attaching_files)
|
|
@@ -46,9 +46,11 @@ your config YAML or on the `ReferenceValidationConfig` object):
|
|
|
46
46
|
|-----|---------|-------------|
|
|
47
47
|
| `fetch_full_text` | `true` | Attempt to obtain full text via the provider chain when a metadata source does not already return full text. |
|
|
48
48
|
| `full_text_providers` | `[pmc, epmc_preprint, unpaywall, openalex]` | Ordered list of provider names to try until one yields usable full text. |
|
|
49
|
+
| `private_cache_dir` | `~/.cache/linkml-reference-validator/private` | Separate research cache for closed/user-library full text; never read by validation. |
|
|
49
50
|
| `pdf_backend` | `pypdf` | Name of the PDF text-extraction backend. |
|
|
50
51
|
| `download_pdfs` | `true` | If true, persist downloaded PDFs to the files cache directory. |
|
|
51
52
|
| `full_text_providers_file` | `null` | Optional path to a YAML file defining custom full-text providers. |
|
|
53
|
+
| `zotero_base_url` | `http://localhost:23119/api/users/0` | Read-only Zotero local API library used by the opt-in `zotero` provider. |
|
|
52
54
|
|
|
53
55
|
Two existing keys are also reused by the full-text machinery:
|
|
54
56
|
|
|
@@ -71,6 +73,106 @@ pdf_backend: pypdf
|
|
|
71
73
|
download_pdfs: true
|
|
72
74
|
```
|
|
73
75
|
|
|
76
|
+
## Private manuscripts in Zotero
|
|
77
|
+
|
|
78
|
+
The opt-in **`zotero`** provider can find non-open manuscripts that are already
|
|
79
|
+
in your personal Zotero library. It matches exact DOI, PMID, or PMCID identifiers;
|
|
80
|
+
it does not automatically accept fuzzy title matches.
|
|
81
|
+
|
|
82
|
+
Zotero must be running, and its local API must be enabled in Zotero's advanced
|
|
83
|
+
settings. Inventory the reference cache before changing it:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
linkml-reference-validator cache enrich \
|
|
87
|
+
--provider zotero \
|
|
88
|
+
--cache-dir references_cache \
|
|
89
|
+
--dry-run
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The report distinguishes `found`, `not_found`, `already_full_text`, and `error`.
|
|
93
|
+
Dry-run is the default and never changes cache files. After reviewing exact
|
|
94
|
+
matches, apply usable text with:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
linkml-reference-validator cache enrich \
|
|
98
|
+
--provider zotero \
|
|
99
|
+
--cache-dir references_cache \
|
|
100
|
+
--apply
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Apply mode does **not** modify `references_cache`. It writes the enriched entry
|
|
104
|
+
to a separate research cache at `~/.cache/linkml-reference-validator/private`
|
|
105
|
+
by default. Agents may inspect that cache for background context, but ordinary
|
|
106
|
+
validation never reads it and never cites it as evidence. Validation therefore
|
|
107
|
+
has the same inputs locally, in CI, and on another contributor's machine.
|
|
108
|
+
|
|
109
|
+
To keep the research cache in a private repository or another secured location:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
linkml-reference-validator cache enrich \
|
|
113
|
+
--provider zotero \
|
|
114
|
+
--cache-dir references_cache \
|
|
115
|
+
--private-cache-dir /path/to/private-reference-cache \
|
|
116
|
+
--apply
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The same location can be configured for all commands:
|
|
120
|
+
|
|
121
|
+
```yaml
|
|
122
|
+
cache_dir: references_cache
|
|
123
|
+
private_cache_dir: /path/to/private-reference-cache
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Zotero-indexed text is preferred. If Zotero has not indexed an attachment, the
|
|
127
|
+
provider downloads it from Zotero's local PDF endpoint and sends it through the
|
|
128
|
+
normal PDF extractor. The source attachment key and `user_library` access type
|
|
129
|
+
are persisted, but the ephemeral localhost URL is not.
|
|
130
|
+
|
|
131
|
+
!!! warning "Keep research caches private"
|
|
132
|
+
|
|
133
|
+
Private cache entries contain extracted manuscript text and may contain a
|
|
134
|
+
copied PDF. Do not place this cache in a public repository or share it
|
|
135
|
+
unless you have permission to redistribute that content.
|
|
136
|
+
|
|
137
|
+
Do not add `zotero` to `full_text_providers`. Even if it is configured there,
|
|
138
|
+
ordinary validation rejects its `user_library` result and continues to public
|
|
139
|
+
providers. Use `cache enrich` when you want to search Zotero.
|
|
140
|
+
|
|
141
|
+
Support for reproducible validation backed by private manuscripts is a future,
|
|
142
|
+
separate feature. The proposed design is a trusted offline job that emits a
|
|
143
|
+
minimal signed excerpt attestation into the public cache. The validator would
|
|
144
|
+
verify the signature using a checked-in public key; neither agents nor CI would
|
|
145
|
+
have the signing key or permission to generate those files directly.
|
|
146
|
+
|
|
147
|
+
## Export a cache to a Zotero collection
|
|
148
|
+
|
|
149
|
+
Export references that still need full text as metadata-only CSL JSON:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
linkml-reference-validator cache export \
|
|
153
|
+
--cache-dir references_cache \
|
|
154
|
+
--format csl-json \
|
|
155
|
+
--needs-full-text \
|
|
156
|
+
--output project-zotero.json
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
The default `--needs-full-text` mode excludes cache entries that already contain
|
|
160
|
+
full text. It also excludes non-publication identifiers, deduplicates by
|
|
161
|
+
normalized DOI and then PMID, and exports only an explicit metadata allowlist:
|
|
162
|
+
title, authors, journal, year, DOI, PMID, and PubMed URL. Cached article text,
|
|
163
|
+
excerpts, provenance, PDFs, and local paths are never exported. Use `--all` only
|
|
164
|
+
when you deliberately want eligible records that already have full text.
|
|
165
|
+
|
|
166
|
+
The exporter refuses to replace an existing output file unless `--force` is
|
|
167
|
+
given. Review the reported counts, then in Zotero choose **File → Import → A
|
|
168
|
+
file**, select the JSON file, and place the imported items in a project-specific
|
|
169
|
+
collection. Zotero supports CSL JSON as a standard import format. After import,
|
|
170
|
+
select the collection and run **Find Full Text**, then rerun `cache enrich`.
|
|
171
|
+
|
|
172
|
+
See [Zotero's standardized-format import instructions](https://www.zotero.org/support/kb/importing_standardized_formats).
|
|
173
|
+
For the complete workflow with screenshots, see
|
|
174
|
+
[Export a Reference Cache to Zotero](export-cache-to-zotero.md).
|
|
175
|
+
|
|
74
176
|
## Preprints
|
|
75
177
|
|
|
76
178
|
Preprints are first-class references. They are increasingly cited for early
|
|
@@ -183,3 +285,46 @@ downloaded PDF lives under the cache directory and can be located at
|
|
|
183
285
|
- [Validating DOIs](validate-dois.md) — DOI metadata sources and supplementary files
|
|
184
286
|
- [Validating Entrez Accessions](validate-entrez.md) — PubMed/PMC references
|
|
185
287
|
- [CLI Reference](../reference/cli.md) — complete command documentation
|
|
288
|
+
|
|
289
|
+
## HTML article checks and cache recovery
|
|
290
|
+
|
|
291
|
+
An OpenAlex or Unpaywall URL may lead to a repository item record containing
|
|
292
|
+
only an abstract and metadata. HTML full-text acquisition now requires an
|
|
293
|
+
identifiable research body: publisher body markup or narrative research sections
|
|
294
|
+
with paragraphs, after removing abstracts and navigation. Length and additional
|
|
295
|
+
metadata text alone do not establish full text. This also applies when a URL
|
|
296
|
+
advertised as a PDF actually returns HTML. Genuine HTML research bodies remain
|
|
297
|
+
eligible, including short bodies above the existing 500-character minimum.
|
|
298
|
+
|
|
299
|
+
Ambiguous layouts are rejected and the next configured provider is tried. The
|
|
300
|
+
fetcher does not crawl repository download links. If every provider completes
|
|
301
|
+
without usable text or an error, the reference retains its original abstract
|
|
302
|
+
and records `full_text_attempted: true`.
|
|
303
|
+
|
|
304
|
+
New `full_text_html` cache entries carry `html_full_text_version: 1`. Older
|
|
305
|
+
Markdown HTML full-text entries without this stamp are refreshed on their next
|
|
306
|
+
validation read. This migration covers all providers because cached plain text
|
|
307
|
+
cannot establish which HTML body structure was present. It does not invalidate
|
|
308
|
+
current PDF, XML, or abstract caches.
|
|
309
|
+
|
|
310
|
+
If refreshing an old HTML entry fails, validation does **not** fall back to that
|
|
311
|
+
entry: its text may be repository metadata rather than article evidence. The
|
|
312
|
+
file remains untouched for inventory/export, and the next validation run retries
|
|
313
|
+
recovery. Once the source is available, normal fetching replaces it with a
|
|
314
|
+
verified article or the available metadata/abstract. Other content types retain
|
|
315
|
+
the existing stale-cache fallback. Legacy `.txt` caches remain a separate,
|
|
316
|
+
read-only compatibility path and are not migrated by this HTML stamp.
|
|
317
|
+
|
|
318
|
+
Research headings establish body presence; they do not filter the accepted
|
|
319
|
+
article's other sections. For example, `Main`, `Case presentation`, and
|
|
320
|
+
`Limitations` remain in an accepted article. A separately marked body is also
|
|
321
|
+
preserved when an abstract heading uses a higher heading level. Without that
|
|
322
|
+
structural boundary, an unmarked structured abstract remains ambiguous and is
|
|
323
|
+
rejected conservatively.
|
|
324
|
+
|
|
325
|
+
A provider's `FullTextLocation.text` (including a custom API `text_field`) is a
|
|
326
|
+
trusted **already-extracted article body** contract. Configure it only for APIs
|
|
327
|
+
that return article text, not arbitrary page text or metadata. Plain extracted
|
|
328
|
+
text cannot be structurally rechecked; raw HTML supplied with an HTML hint still
|
|
329
|
+
passes the body classifier. The acceptance stamp records that either the HTML
|
|
330
|
+
check or this trusted provider contract was used.
|
|
@@ -13,6 +13,21 @@ After validating your data files, you may find validation errors due to:
|
|
|
13
13
|
|
|
14
14
|
The `repair` command attempts to fix these issues automatically or flags them for manual review.
|
|
15
15
|
|
|
16
|
+
### Typographic ligatures already match
|
|
17
|
+
|
|
18
|
+
Validation folds Latin compatibility ligatures on both the reference content and
|
|
19
|
+
the quote, including each part separated by `...`. For example, PDF-extracted
|
|
20
|
+
`amyloid fibrils` matches `amyloid fibrils` without a repair. The supported folds
|
|
21
|
+
are `ff → ff`, `fi → fi`, `fl → fl`, `ffi → ffi`, `ffl → ffl`, `ſt/st → st`, and
|
|
22
|
+
`IJ/ij → IJ/ij`. IJ is included because Unicode gives it a compatibility
|
|
23
|
+
decomposition into I and J; ordinary case normalization still applies.
|
|
24
|
+
|
|
25
|
+
The distinct letters `Æ/æ` and `Œ/œ` remain distinct from `AE/ae` and `OE/oe`.
|
|
26
|
+
Equating these letters would accept spelling changes beyond typographic repair.
|
|
27
|
+
Validation uses an explicit ligature table instead of broad Unicode NFKC
|
|
28
|
+
normalization so this change does not equate scientific notation such as `H₂O`
|
|
29
|
+
with `H2O`, `10⁶` with `106`, or the micro sign `µ` with Greek `μ`.
|
|
30
|
+
|
|
16
31
|
## Quick Start
|
|
17
32
|
|
|
18
33
|
### Repair a Single Quote
|
|
@@ -112,7 +127,7 @@ Flags text that appears fabricated or hallucinated:
|
|
|
112
127
|
|
|
113
128
|
```
|
|
114
129
|
RECOMMENDED REMOVALS:
|
|
115
|
-
PMID:34567890 at evidence[2]:
|
|
130
|
+
PMID:34567890 at evidence[2].supporting_text:
|
|
116
131
|
Similarity: 8%
|
|
117
132
|
Snippet: 'This completely made up text...'
|
|
118
133
|
```
|
|
@@ -290,6 +305,33 @@ The supporting text wasn't found in the reference. Possible causes:
|
|
|
290
305
|
- Wrong PMID
|
|
291
306
|
- AI-generated/hallucinated quote
|
|
292
307
|
|
|
308
|
+
### "Supporting text is empty"
|
|
309
|
+
|
|
310
|
+
The excerpt is empty or whitespace-only, so there is nothing to match against
|
|
311
|
+
the reference. This is usually a bug in whatever generated the data (for
|
|
312
|
+
example, a string slice with a backwards range yielding `""`).
|
|
313
|
+
|
|
314
|
+
Empty excerpts cannot be repaired automatically — there is no text to correct,
|
|
315
|
+
and fuzzy-matching nothing against the reference would invent a quote. They
|
|
316
|
+
appear under **INSUFFICIENT EXCERPTS (nothing to verify)** in the report, so
|
|
317
|
+
you can supply the real quote or drop the evidence item.
|
|
318
|
+
|
|
319
|
+
They are deliberately *not* counted as removals. A removal recommendation means
|
|
320
|
+
"this quote does not match the reference", a verdict reached by comparing the
|
|
321
|
+
two; here no comparison happened. So `removal_count` excludes them and the
|
|
322
|
+
action type is `INSUFFICIENT_EXCERPT`, not `REMOVAL` — worth knowing if you
|
|
323
|
+
script against the report. They do still make `repair data` exit non-zero.
|
|
324
|
+
|
|
325
|
+
### "Supporting text is too short"
|
|
326
|
+
|
|
327
|
+
The excerpt is below the `min_excerpt_length` you configured (off by default,
|
|
328
|
+
and set under `validation:`; see
|
|
329
|
+
[How It Works](../concepts/how-it-works.md)). A very short excerpt matches
|
|
330
|
+
almost any paper by chance, so it is weak evidence even when the match succeeds.
|
|
331
|
+
|
|
332
|
+
Like empty excerpts, these report under **INSUFFICIENT EXCERPTS** rather than
|
|
333
|
+
being repaired: there is no way to guess which longer passage the curator meant.
|
|
334
|
+
|
|
293
335
|
### "Reference content not available"
|
|
294
336
|
|
|
295
337
|
The reference exists but has no retrievable content:
|
|
@@ -89,7 +89,7 @@ URLs are cached the same way as PMID and DOI references:
|
|
|
89
89
|
|
|
90
90
|
### Title Extraction
|
|
91
91
|
|
|
92
|
-
For HTML pages, the title is
|
|
92
|
+
For HTML pages, the title is the `citation_title` meta tag when present, then the `<title>` tag. For PDFs, the validator tries a publisher landing page's `citation_title` and then the PDF's embedded title. When neither is found, and for other content types, the URL itself is used as the title. See [Validating URLs](validate-urls.md#titles).
|
|
93
93
|
|
|
94
94
|
### Example: Validating Against a Web Page
|
|
95
95
|
|
|
@@ -145,6 +145,6 @@ Both file and URL references work in LinkML data files:
|
|
|
145
145
|
|
|
146
146
|
## Limitations
|
|
147
147
|
|
|
148
|
-
- **PDF files**: Not yet supported
|
|
148
|
+
- **Local PDF files**: Not yet supported as `file:` references. PDFs fetched by `url:` are supported.
|
|
149
149
|
- **Authentication**: URLs requiring login are not supported
|
|
150
150
|
- **Dynamic content**: JavaScript-rendered pages may not work
|
|
@@ -40,6 +40,10 @@ clinicaltrials:NCT00000001
|
|
|
40
40
|
CLINICALTRIALS:NCT00000001
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
These forms normalize to `clinicaltrials:NCT00000001` and share the cache file
|
|
44
|
+
`clinicaltrials_NCT00000001.md`. Existing files with that canonical name are
|
|
45
|
+
reused without renaming or fetching the trial again.
|
|
46
|
+
|
|
43
47
|
## Prefix Aliases and Normalization
|
|
44
48
|
|
|
45
49
|
If your data uses alternate prefix styles (e.g., the legacy `NCT:` prefix), configure normalization in `.linkml-reference-validator.yaml`:
|
|
@@ -15,8 +15,8 @@ The linkml-reference-validator supports validating references that point to web
|
|
|
15
15
|
When a reference field contains a URL, the validator:
|
|
16
16
|
|
|
17
17
|
1. Fetches the web page content
|
|
18
|
-
2. Extracts the page title
|
|
19
|
-
3.
|
|
18
|
+
2. Extracts the page title (see [Titles](#titles))
|
|
19
|
+
3. Sanitizes HTML and caches the content for future validations
|
|
20
20
|
4. Validates your supporting text against the page content
|
|
21
21
|
|
|
22
22
|
## URL Format
|
|
@@ -79,14 +79,45 @@ When the validator encounters a URL reference, it:
|
|
|
79
79
|
|
|
80
80
|
The fetcher stores:
|
|
81
81
|
|
|
82
|
-
- **Title**:
|
|
83
|
-
- **Content**:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
HTML
|
|
88
|
-
|
|
89
|
-
|
|
82
|
+
- **Title**: See [Titles](#titles)
|
|
83
|
+
- **Content**: Sanitized HTML for HTML pages; plain text and XML as received;
|
|
84
|
+
extracted text for PDFs
|
|
85
|
+
- **Content type**: `url` for pages, `full_text_pdf` for PDFs with text
|
|
86
|
+
|
|
87
|
+
HTML is sanitized before it is cached, because caches are often committed to
|
|
88
|
+
public repositories and page scripts routinely carry signed asset URLs and API
|
|
89
|
+
keys. `<script>`, `<style>`, `<noscript>` and `<template>` elements and HTML
|
|
90
|
+
comments are removed. So are `<meta>`, `<link>` and `<base>`, which hold nothing
|
|
91
|
+
but attributes. Every other tag attribute is removed except `rowspan`,
|
|
92
|
+
`colspan` and `scope`, which carry table structure. Body markup and text are
|
|
93
|
+
kept. There is no HTML-to-text conversion, so tag names can still surface
|
|
94
|
+
during normalization. If validation fails because tags interrupt the text,
|
|
95
|
+
consider extracting plain text and validating against a local `file:`
|
|
96
|
+
reference instead.
|
|
97
|
+
|
|
98
|
+
#### Titles
|
|
99
|
+
|
|
100
|
+
For HTML pages the title is the `citation_title` meta tag when present (the
|
|
101
|
+
Highwire / Google Scholar convention, which names the article rather than the
|
|
102
|
+
site), then the `<title>` tag.
|
|
103
|
+
|
|
104
|
+
For PDFs the validator tries, in order:
|
|
105
|
+
|
|
106
|
+
1. The `citation_title` of the publisher's landing page, where a known rule
|
|
107
|
+
maps the PDF URL to it. Currently J-STAGE: `.../_pdf` becomes
|
|
108
|
+
`.../_article`.
|
|
109
|
+
2. The PDF's embedded `/Title` metadata, ignoring placeholders such as
|
|
110
|
+
`Microsoft Word - draft.doc`, bare filenames and `Untitled`.
|
|
111
|
+
3. The URL itself.
|
|
112
|
+
|
|
113
|
+
So a PDF entry whose `title` equals its URL is one for which no title was
|
|
114
|
+
found.
|
|
115
|
+
|
|
116
|
+
The landing-page rules and the placeholder titles are kept in
|
|
117
|
+
`src/linkml_reference_validator/etl/rules.py`, with the other publisher and
|
|
118
|
+
site rules. Each rule sits beside examples of what it must and must not match.
|
|
119
|
+
To support another publisher, add a rule there with at least one example;
|
|
120
|
+
`tests/test_rules.py` fails for a rule without one.
|
|
90
121
|
|
|
91
122
|
### 3. Caching
|
|
92
123
|
|
|
@@ -104,9 +135,9 @@ content_type: url
|
|
|
104
135
|
## Content
|
|
105
136
|
|
|
106
137
|
<html>
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
138
|
+
<head>
|
|
139
|
+
<title>Chapter 3: Cell Structure and Function</title>
|
|
140
|
+
</head>
|
|
110
141
|
...
|
|
111
142
|
```
|
|
112
143
|
|
|
@@ -145,9 +176,10 @@ URL validation is designed for static web pages. It may not work well with:
|
|
|
145
176
|
|
|
146
177
|
### Raw Content
|
|
147
178
|
|
|
148
|
-
The validator stores
|
|
179
|
+
The validator stores sanitized page markup, not extracted text. For HTML pages:
|
|
149
180
|
|
|
150
|
-
- HTML tags are preserved in the cache
|
|
181
|
+
- HTML tags are preserved in the cache, without attributes other than
|
|
182
|
+
`rowspan`, `colspan` and `scope`
|
|
151
183
|
- The text normalization during validation handles most cases
|
|
152
184
|
- Complex HTML layouts may require careful text extraction
|
|
153
185
|
|