diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 87e01f23..4e11f4a1 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -80,9 +80,10 @@ src/quantecon_book_theme/ - **Regression tests**: Tests compare generated HTML against golden files in `tests/test_build/` ### Code Quality Workflow -- Always run `pre-commit run --all-files` before committing +- **CRITICAL**: ALWAYS run `pre-commit run --all-files` before committing to GitHub - Pre-commit includes: black (formatting), flake8 (linting), YAML/JSON validation - CI will fail if pre-commit checks don't pass +- If you make changes to Python or SCSS files, run pre-commit before `git commit` ## Troubleshooting @@ -116,10 +117,13 @@ pre-commit install # Development workflow npm run build # Compile assets (2.5-3 seconds, VALIDATED) tox -e docs-live # Live development server (5-10 minutes) -pre-commit run --all-files # Code quality checks (2-5 minutes, VALIDATED) +pre-commit run --all-files # Code quality checks (2-5 minutes, VALIDATED) - RUN BEFORE COMMITTING flake8 src/ # Python linting (few seconds, VALIDATED) black --check src/ # Formatting check (few seconds, VALIDATED) +# Before committing to GitHub +pre-commit run --all-files # CRITICAL: Always run before git commit + # Testing and CI tox # Full test suite (5-15 minutes) tox -e docs-update # Build documentation (5-15 minutes) diff --git a/src/quantecon_book_theme/assets/styles/index.scss b/src/quantecon_book_theme/assets/styles/index.scss index 6531dc62..e48a4c6d 100644 --- a/src/quantecon_book_theme/assets/styles/index.scss +++ b/src/quantecon_book_theme/assets/styles/index.scss @@ -298,6 +298,27 @@ body { } } +// Fix excess spacing in streaming output (Issue #325) +// Remove all spacing between consecutive streaming outputs +.cell_output .output.stream + .output.stream { + margin-top: 0 !important; +} + +// Remove internal spacing from all streaming output elements +.cell_output .output.stream { + .highlight { + margin-top: 0 !important; + margin-bottom: 0 !important; + + // Remove margin and padding from pre elements + pre { + margin: 0 !important; + padding-top: 0 !important; + padding-bottom: 0 !important; + } + } +} + .section, .reference, .math { diff --git a/tests/sites/base/section1/index.md b/tests/sites/base/section1/index.md index 6958b84a..a2dbb87b 100644 --- a/tests/sites/base/section1/index.md +++ b/tests/sites/base/section1/index.md @@ -3,6 +3,7 @@ ```{toctree} page1 ntbk +ntbk_streaming ntbkmd ntbk_octave ntbk_julia diff --git a/tests/sites/base/section1/ntbk_streaming.ipynb b/tests/sites/base/section1/ntbk_streaming.ipynb new file mode 100644 index 00000000..aa32a1f7 --- /dev/null +++ b/tests/sites/base/section1/ntbk_streaming.ipynb @@ -0,0 +1,117 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Test Streaming Output\n", + "\n", + "This notebook tests streaming output from multiple print statements." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Error at iteration 25 is 40.0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Error at iteration 50 is 20.0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Error at iteration 75 is 13.333333333333334.\n" + ] + } + ], + "source": [ + "# Test with streaming output from loop\n", + "# Each print statement creates a separate stream output\n", + "for i in [25, 50, 75]:\n", + " error = 100 / (i / 10)\n", + " print(f\"Error at iteration {i} is {error}.\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Line 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Line 2\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Line 3\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Line 4\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Line 5\n" + ] + } + ], + "source": [ + "# Test with multiple consecutive print statements\n", + "# Each creates a separate stream output\n", + "for i in range(1, 6):\n", + " print(f\"Line {i}\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.0" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/tests/test_build.py b/tests/test_build.py index ab996cd4..da47550a 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -422,3 +422,49 @@ def test_qetheme_code_style(sphinx_build): # String "true" should be treated as True assert "use-pygments-style" not in body_tag.get("class", []) sphinx_build.clean() + + +def test_streaming_output_spacing(sphinx_build): + """Test that streaming output structure supports CSS spacing fix. + + This test verifies the fix for issue #325 where consecutive stream outputs + have comprehensive CSS applied to remove excessive spacing. + """ + sphinx_build.copy() + sphinx_build.build() + + # Get the streaming output notebook page + streaming_html = sphinx_build.get("section1/ntbk_streaming.html") + + # Find all stream output divs + stream_outputs = streaming_html.find_all("div", class_="output") + stream_divs = [div for div in stream_outputs if "stream" in div.get("class", [])] + + # Should have multiple stream outputs from the test notebook + assert ( + len(stream_divs) >= 8 + ), f"Should have at least 8 streaming output elements, found {len(stream_divs)}" + + # Verify we have consecutive streaming outputs (adjacent siblings) + cell_outputs = streaming_html.find_all("div", class_="cell_output") + assert len(cell_outputs) >= 2, "Should have at least 2 cells with outputs" + + # At least one cell should have consecutive stream outputs for CSS to target + found_consecutive = False + for cell_output in cell_outputs: + stream_children = [ + child + for child in cell_output.children + if child.name == "div" + and "output" in child.get("class", []) + and "stream" in child.get("class", []) + ] + if len(stream_children) >= 2: + found_consecutive = True + break + + assert ( + found_consecutive + ), "Should have consecutive stream outputs for CSS fix to apply" + + sphinx_build.clean() diff --git a/tests/test_build/test_build_book.html b/tests/test_build/test_build_book.html index f9af32a3..709992bd 100644 --- a/tests/test_build/test_build_book.html +++ b/tests/test_build/test_build_book.html @@ -41,19 +41,24 @@ 3.2. A test notebook +