Repository navigation
Implement the md-lines hook: one sentence per line in Markdown #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
ef2a61a
Implement the md-lines hook: one sentence per line in Markdown
CodyCBakerPhD 457265a
Wrap a long test line for ruff
CodyCBakerPhD 483a370
Read the version from the installed package metadata
CodyCBakerPhD ddb35a9
Target the latest Python only; drop the python -m entry point
CodyCBakerPhD 87143b0
Update README.md
CodyCBakerPhD a87ecc1
Generate the data model from a LinkML schema and split out the constants
CodyCBakerPhD b5ef454
Adopt the historia conventions: AGENTS.md, relative imports, CI rename
CodyCBakerPhD 2cc5030
Upload coverage to Codecov from CI
CodyCBakerPhD f029bc8
CI: run only what pre-commit.ci cannot
CodyCBakerPhD 203bbd9
Update README.md
CodyCBakerPhD File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| name: Continuous Integration | ||
|
|
||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: [main] | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| tests: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v7 | ||
| with: | ||
| persist-credentials: false | ||
| - uses: actions/setup-python@v7 | ||
| with: | ||
| # Latest stable Python only; pyproject.toml sets the floor. | ||
| python-version: "3.x" | ||
| - run: pip install -e ".[dev]" | ||
| - run: pytest --cov=src/md_lines --cov-report=xml | ||
| - name: Upload coverage to Codecov | ||
| uses: codecov/codecov-action@v7 | ||
| with: | ||
| token: ${{ secrets.CODECOV_TOKEN }} | ||
| files: ./coverage.xml | ||
| fail_ci_if_error: true | ||
|
|
||
| # pre-commit.ci runs the other hooks on every pull request. It cannot run this repository's | ||
| # own md-lines hook (`language: system`, skipped in .pre-commit-config.yaml), and it does not | ||
| # test installing the hook the way a consumer does, so this job covers those two things. | ||
| hook: | ||
| name: md-lines hook and try-repo | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v7 | ||
| with: | ||
| persist-credentials: false | ||
| - uses: actions/setup-python@v7 | ||
| with: | ||
| python-version: "3.x" | ||
| - run: pip install -e ".[dev]" | ||
| - name: This repository's own md-lines hook on its Markdown | ||
| run: pre-commit run md-lines --all-files --show-diff-on-failure | ||
| - name: Install the hook the way a consumer would | ||
| run: pre-commit try-repo . md-lines --files README.md --verbose | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| __pycache__/ | ||
| *.pyc | ||
| *.egg-info/ | ||
| dist/ | ||
| build/ | ||
| .pytest_cache/ | ||
| .venv/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| # Based on the pre-commit setup of CodyCBakerPhD/historia. | ||
| ci: | ||
| autoupdate_schedule: quarterly | ||
| # pre-commit.ci cannot run `language: system` hooks; the GitHub Actions workflow runs this one. | ||
| skip: [md-lines] | ||
|
|
||
| default_install_hook_types: | ||
| - pre-commit | ||
|
|
||
| # src/md_lines/models.py is generated from the LinkML schema; the hooks leave it alone. | ||
| exclude: ^src/md_lines/models\.py$ | ||
|
|
||
| repos: | ||
| - repo: https://github.com/pre-commit/pre-commit-hooks | ||
| rev: v6.0.0 | ||
| hooks: | ||
| - id: check-yaml | ||
| - id: end-of-file-fixer | ||
| - id: trailing-whitespace | ||
| args: ["--markdown-linebreak-ext=md"] | ||
| - id: check-json | ||
| - id: check-toml | ||
| - id: check-added-large-files | ||
| - id: check-case-conflict | ||
| - id: check-merge-conflict | ||
|
|
||
| - repo: https://github.com/python-jsonschema/check-jsonschema | ||
| rev: 0.38.2 | ||
| hooks: | ||
| - id: check-github-workflows | ||
| args: ["--verbose"] | ||
|
|
||
| - repo: https://github.com/psf/black-pre-commit-mirror | ||
| rev: 26.10.0 | ||
| hooks: | ||
| - id: black | ||
|
|
||
| # ruff lints and sorts imports (its isort rules are selected in pyproject.toml); black formats. | ||
| - repo: https://github.com/astral-sh/ruff-pre-commit | ||
| rev: v0.16.10 | ||
| hooks: | ||
| - id: ruff | ||
| args: [ --fix ] | ||
|
|
||
| - repo: https://github.com/codespell-project/codespell | ||
| rev: v2.4.3 | ||
| hooks: | ||
| - id: codespell | ||
| additional_dependencies: | ||
| - tomli | ||
|
|
||
| - repo: local | ||
| hooks: | ||
| - id: md-lines | ||
| name: md-lines (this repository's own hook) | ||
| entry: md-lines | ||
| language: system | ||
| types: [markdown] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| - id: md-lines | ||
| name: md-lines (one sentence per line in Markdown) | ||
| description: >- | ||
| Reflow Markdown prose so that each sentence sits on its own line. Code, tables, | ||
| headings, HTML and front matter are left alone. Files that needed changes are | ||
| rewritten and the hook fails once so the changes can be reviewed and staged. | ||
| entry: md-lines | ||
| language: python | ||
| types: [markdown] | ||
| minimum_pre_commit_version: "2.9.0" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| # Agent instructions | ||
|
|
||
| ## Commits and PRs | ||
|
|
||
| - Always run `pre-commit run --all-files` before committing and pushing changes | ||
| - Always link PRs to issues when possible | ||
| - PR titles should be human-readable and in the past tense. They should NOT use conventional commit style. | ||
| - Every commit must include a `Co-Authored-By` trailer identifying your tool name and version and your underlying model and version. Format (replace all `<…>` placeholders with actual values): `Co-Authored-By: <Tool> <tool-version> / <Model> <model-version> <noreply@vendor-domain>` | ||
|
|
||
| ## Versioning and changelog | ||
|
|
||
| - Bump the version in `pyproject.toml` once per PR when any file under `src/` or `pyproject.toml` itself changes. That is the only place to edit it; `md_lines.__version__` reads it from the installed package metadata. Do NOT bump for changes that are purely CI/workflow, documentation, or configuration (e.g., GitHub Actions workflows, `AGENTS.md`, `README.md` badges). | ||
| - The changelog follows the version. If the PR does not bump `pyproject.toml`, it does not need a `CHANGELOG.md` entry either. A documentation-only change needs neither. | ||
| - Otherwise, add a short entry to the `## Upcoming` section of `CHANGELOG.md` under the appropriate subsection (`### 🚀 Enhancement`, `### 🐛 Bug Fix`, `### 📝 Documentation`, `### 🔩 Dependency Updates`, `### 🏠 Internal`). Include the PR link at the end of each entry in the format `([#N](https://github.com/CodyCBakerPhD/md-lines-pre-commit/pull/N))`. Create the `## Upcoming` section or subsection if it does not yet exist. | ||
| - Releases are git tags of the form `vX.Y.Z`, which is what consumers pin as `rev:` in their pre-commit configuration. | ||
|
|
||
| ## Code style | ||
|
|
||
| - Require keyword-only arguments `(*, ...)` for multi-input functions. For any function with exactly one caller-supplied parameter (excluding `self` and `cls`), require positional-only usage with the `/` designator. | ||
| - Always add new imports at the top of the file. The only exception is when a local import is needed to avoid a circular dependency. | ||
| - For external dependencies, use the full module import style (e.g., `import xyz; xyz.abc`) rather than `from xyz import abc`. | ||
| - For internal imports, always use relative style (e.g., `from .foo import bar`). | ||
| - Prefer assigning return values to named locals before `return` when this improves readability and debugger breakpoint placement. | ||
| - Avoid excessive em-dashes, colons, and semicolons in written text such as documentation. Prefer breaking into separate, shorter sentences instead. | ||
| - Write documentation, comments and messages in American English. codespell enforces it. | ||
| - In Markdown, put each sentence on its own line. This repository's own hook enforces it. | ||
| - Favor defining one-word names for CLI flags, then map those onto longer, more explicit keyword arguments at the API level. | ||
| - Keep inline comments sparse. Only explain non-obvious "why", not "what" the code does. Prefer self-documenting code and clear names over narration; do not annotate routine logic. | ||
|
|
||
| ## Data model | ||
|
|
||
| - The data model (`Options`, `Problem`, `Result`, `Paragraph`) is defined in the LinkML schema `src/md_lines/schema/md_lines.yaml`. Change the schema, never the generated code. | ||
| - `src/md_lines/models.py` is generated from the schema with `gen-python --no-metadata src/md_lines/schema/md_lines.yaml > src/md_lines/models.py`. Regenerate it after every schema change; a test fails when the two drift apart. | ||
| - Module-level constants (the abbreviation list, the parser, the regular expressions, `DEFAULT_OPTIONS`) live in `src/md_lines/globals.py`, not next to the models. | ||
|
|
||
| ## Tests | ||
|
|
||
| - To the best of your ability, ensure tests are passing before pushing. | ||
| - Follow assertion style: actual on left, expected on right. | ||
| - Always mark AI-generated tests with the `ai_generated` pytest marker. | ||
| - Use `pytest.mark.parametrize` wherever appropriate to reduce duplication in test cases. | ||
| - Avoid importing private API (names with a leading underscore) in tests. Always import from what is publicly exposed through `__init__.py` files. | ||
| - When monkeypatching internal imports in tests, target the importing module's binding (e.g., `foo.baz`), not the original definition module (e.g., `foo._bar.baz`). | ||
|
|
||
| ## Module and API conventions | ||
|
|
||
| - Never expose private names (those with a leading underscore) in any module's `__all__`. | ||
| - Never include code other than imports, `__all__`, simple import errors, or magic `__dir__` overrides in any `__init__.py` file. | ||
| - Do not add compatibility aliases when renaming functions. Update all call sites to the canonical name instead. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # Changelog | ||
|
|
||
| ## Upcoming | ||
|
|
||
| ### 🚀 Enhancement | ||
|
|
||
| - Initial implementation of the `md-lines` hook, which puts each Markdown sentence on its own line. ([#1](https://github.com/CodyCBakerPhD/md-lines-pre-commit/pull/1)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,64 @@ | ||
| # md-lines-pre-commit | ||
| A pre-commit hook for ensuring distinct breaks within markdown files. | ||
|
|
||
| A [pre-commit](https://pre-commit.com) hook that puts each sentence of a Markdown file on its own line. | ||
|
|
||
| Wrapped sentences are joined back onto one line, and lines that hold several sentences are split, so diffs and reviews work sentence by sentence. | ||
|
|
||
| Everything that is not prose stays exactly as it is. | ||
|
|
||
| ## Usage | ||
|
|
||
| Add the hook to your `.pre-commit-config.yaml`: | ||
|
|
||
| ```yaml | ||
| repos: | ||
| - repo: https://github.com/CodyCBakerPhD/md-lines-pre-commit | ||
| rev: v0.1.0 | ||
| hooks: | ||
| - id: md-lines | ||
| ``` | ||
|
|
||
| Or directly from the command line (after installing with `pip install git+https://github.com/CodyCBakerPhD/md-lines-pre-commit`): | ||
|
|
||
| ```sh | ||
| md-lines README.md docs/*.md # rewrite in place, exit 1 if anything changed | ||
| md-lines --check --diff README.md # only report, with a diff, do not write | ||
| ``` | ||
|
|
||
| ## What it changes | ||
|
|
||
| This hook splits the breaks within paragraphs across lines, primarily sentences but also including list items and block quotes. | ||
| Within a paragraph: | ||
|
|
||
| - A line that does not end with `.`, `!` or `?` (closing quotes, parentheses or emphasis markers may follow) is joined with the next line, because the sentence was wrapped. | ||
| - A line holding several sentences is split at each sentence end, when what follows starts with an uppercase letter, a digit, an opening quote, bracket or emphasis marker, or inline code. | ||
| - List items are joined but not split, so an item may hold several sentences on its line; `--split-lists` splits them too, indented to the item's text. | ||
| - Block quote markers (`>`) and list indentation are reproduced on the new lines. | ||
| - Hard line breaks (two trailing spaces or a trailing backslash) are kept. | ||
|
|
||
| What is never touched: headings, code blocks and fences, tables, HTML blocks and comments, link reference definitions, thematic breaks, YAML or TOML front matter. | ||
|
|
||
| Block structure comes from a CommonMark parser ([markdown-it-py](https://github.com/executablebooks/markdown-it-py)), not from guessing at line prefixes, so a wrapped line that happens to start with a link or an emphasis marker is still recognized as the continuation of its sentence. | ||
|
|
||
| Sentence ends are not detected inside inline code, link destinations, autolinks, inline HTML, bare URLs or `$math$`, nor after common abbreviations (`e.g.`, `etc.`, `Fig.`, `Dr.`, months and so on), initials (`J. Smith`), dotted abbreviations (`U.S.`) or an enumerator at the start of a line (`1.`). | ||
| A bold lead-in such as `**Note.**` stays attached to the sentence it introduces, and no split happens inside unbalanced bold markers, brackets or parentheses. | ||
|
|
||
| ## Options | ||
|
|
||
| | Option | Default | Meaning | | ||
| | --- | --- | --- | | ||
| | `--check` | off | Report what would change and exit 1 instead of rewriting files. | | ||
| | `--diff` | off | Print a unified diff of the changes. | | ||
| | `--split-lists` | off | Split sentences inside list items as well. | | ||
| | `--keep-breaks-after CHARS` | `.!?` | Keep an existing line break after any of these characters. Add `:;` to keep breaks after colons and semicolons; sentences are never split there. | | ||
| | `--abbreviations LIST` | none | Comma-separated words ending in a period that do not end a sentence, added to the built-in list. | | ||
| | `--abbreviations-file PATH` | none | File with one such word per line; blank lines and `#` comments are ignored. | | ||
| | `--no-default-abbreviations` | off | Start from an empty abbreviation list. | | ||
| | `-q`, `--quiet` | off | Do not list the problems found. | | ||
|
|
||
| Pass options through pre-commit with `args`: | ||
|
|
||
| ```yaml | ||
| - id: md-lines | ||
| args: ["--split-lists", "--abbreviations", "chap.,sect."] | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| # Development | ||
|
|
||
| ```sh | ||
| pip install -e ".[dev]" | ||
| pytest | ||
| pre-commit run --all-files | ||
| ``` | ||
|
|
||
| The `dev` extra brings pytest, pre-commit and [LinkML](https://linkml.io). | ||
| Conventions for contributors and coding agents are in [AGENTS.md](../AGENTS.md). | ||
| The hook is used on this repository's own Markdown through `.pre-commit-config.yaml`. | ||
|
|
||
| ## Layout | ||
|
|
||
| - `src/md_lines/schema/md_lines.yaml` defines the data model (`Options`, `Problem`, `Result`, `Paragraph`) as a LinkML schema. | ||
| - `src/md_lines/models.py` is generated from the schema and is not edited by hand; the formatters skip it, and a test fails when it and the schema drift apart. | ||
| - `src/md_lines/globals.py` holds the module-level constants: the abbreviation list, the parser, the regular expressions and `DEFAULT_OPTIONS`. | ||
| - `src/md_lines/reflow.py` holds the reflow functions only, and `src/md_lines/cli.py` the command. | ||
| - `__version__` is read from the installed package metadata, so `pyproject.toml` is the only place the version is written. | ||
|
|
||
| After changing the schema, regenerate the model: | ||
|
|
||
| ```sh | ||
| gen-python --no-metadata src/md_lines/schema/md_lines.yaml > src/md_lines/models.py | ||
| ``` | ||
|
|
||
| ## Repository checks | ||
|
|
||
| The pre-commit configuration follows [historia](https://github.com/CodyCBakerPhD/historia): pre-commit-hooks, check-github-workflows, black, ruff (lint plus isort rules, with `--fix`), codespell with the `en-GB_to_en-US` dictionary so the text stays in American English, and this repository's own `md-lines` hook. | ||
| pre-commit.ci runs the hooks on every pull request, except this repository's own `md-lines` hook, which it cannot run. | ||
| The Actions workflow runs the tests on the newest Python release, runs that one hook, and installs the hook the way a consumer does with `pre-commit try-repo`. | ||
| The tests job uploads coverage to [Codecov](https://codecov.io/gh/CodyCBakerPhD/md-lines-pre-commit) and fails when the upload does, so the repository needs a `CODECOV_TOKEN` secret (Settings, Secrets and variables, Actions). | ||
|
|
||
| ## Exit status | ||
|
|
||
| `md-lines` exits 0 when nothing needed changing, 1 when files were (or in `--check` mode would be) rewritten, and 2 when a file could not be read. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| [build-system] | ||
| requires = ["hatchling"] | ||
| build-backend = "hatchling.build" | ||
|
|
||
| [project] | ||
| name = "md-lines-pre-commit" | ||
| version = "0.1.0" | ||
| description = "pre-commit hook that puts each Markdown sentence on its own line" | ||
| readme = "README.md" | ||
| requires-python = ">=3.13" | ||
| dependencies = ["markdown-it-py>=3.0", "linkml-runtime>=1.9"] | ||
| keywords = ["markdown", "pre-commit", "semantic line breaks", "sentence per line"] | ||
| classifiers = [ | ||
| "Programming Language :: Python :: 3", | ||
| "Programming Language :: Python :: 3.13", | ||
| "Programming Language :: Python :: 3.14", | ||
| "Topic :: Text Processing :: Markup :: Markdown", | ||
| ] | ||
|
|
||
| [project.optional-dependencies] | ||
| test = ["pytest>=7"] | ||
| # Regenerating src/md_lines/models.py from the LinkML schema, and the test that checks it. | ||
| dev = ["pytest>=7", "pytest-cov", "linkml>=1.9", "pre-commit"] | ||
|
|
||
| [project.scripts] | ||
| md-lines = "md_lines.cli:main" | ||
|
|
||
| [project.urls] | ||
| Repository = "https://github.com/CodyCBakerPhD/md-lines-pre-commit" | ||
|
|
||
| [tool.hatch.build.targets.wheel] | ||
| packages = ["src/md_lines"] | ||
|
|
||
| [tool.coverage.run] | ||
| # Generated from the LinkML schema; its many unused branches are not ours to cover. | ||
| omit = ["src/md_lines/models.py"] | ||
|
|
||
| [tool.pytest.ini_options] | ||
| testpaths = ["tests"] | ||
| markers = [ | ||
| "ai_generated: mark test as AI-generated", | ||
| ] | ||
|
|
||
| [tool.black] | ||
| line-length = 100 | ||
| target-version = ["py313"] | ||
| # Generated from src/md_lines/schema/md_lines.yaml; regenerate instead of editing. | ||
| extend-exclude = "src/md_lines/models\\.py" | ||
|
|
||
| [tool.ruff] | ||
| line-length = 100 | ||
| target-version = "py313" | ||
| # Generated from src/md_lines/schema/md_lines.yaml; regenerate instead of editing. | ||
| extend-exclude = ["src/md_lines/models.py"] | ||
|
|
||
| [tool.ruff.lint] | ||
| select = ["E", "F", "I", "UP", "B"] | ||
|
|
||
| [tool.ruff.lint.isort] | ||
| known-first-party = ["md_lines"] | ||
|
|
||
| [tool.codespell] | ||
| skip = ".git,*.lock" | ||
| # Also flag British spellings: the project is written in American English. | ||
| builtin = "clear,rare,en-GB_to_en-US" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| """Put each Markdown sentence on its own line.""" | ||
|
|
||
| from ._version import __version__ as __version__ | ||
| from .globals import DEFAULT_ABBREVIATIONS, DEFAULT_OPTIONS | ||
| from .models import Options, Paragraph, Problem, Result | ||
| from .reflow import reflow, split_sentences | ||
|
|
||
| __all__ = [ | ||
| "DEFAULT_ABBREVIATIONS", | ||
| "DEFAULT_OPTIONS", | ||
| "Options", | ||
| "Paragraph", | ||
| "Problem", | ||
| "Result", | ||
| "reflow", | ||
| "split_sentences", | ||
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| """The installed version. | ||
|
|
||
| It is read from the package metadata, so pyproject.toml stays the only place the version is written. | ||
| """ | ||
|
|
||
| import importlib.metadata | ||
|
|
||
| try: | ||
| __version__ = importlib.metadata.version("md-lines-pre-commit") | ||
| except importlib.metadata.PackageNotFoundError: # a checkout that was not pip-installed | ||
| __version__ = "0+unknown" |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.