Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- Added `@generated` marker comment to HTML and SVG exports

## [14.2.0] - 2025-10-09

### Changed
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ The following people have contributed to the development of Rich:
- [Felipe Guedes](https://github.com/guedesfelipe)
- [Min RK](https://github.com/minrk)
- [Clément Robert](https://github.com/neutrinoceros)
- [Jack Rosenthal](https://github.com/jackrosenthal)
- [Brian Rutledge](https://github.com/bhrutledge)
- [Tushar Sadhwani](https://github.com/tusharsadhwani)
- [Luca Salvarani](https://github.com/LukeSavefrogs)
Expand Down
3 changes: 2 additions & 1 deletion rich/_export_format.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
CONSOLE_HTML_FORMAT = """\
<!DOCTYPE html>
<!-- @generated with Rich https://www.textualize.io -->
<html>
<head>
<meta charset="UTF-8">
Expand All @@ -19,7 +20,7 @@

CONSOLE_SVG_FORMAT = """\
<svg class="rich-terminal" viewBox="0 0 {width} {height}" xmlns="http://www.w3.org/2000/svg">
<!-- Generated with Rich https://www.textualize.io -->
<!-- @generated with Rich https://www.textualize.io -->
<style>

@font-face {{
Expand Down
8 changes: 4 additions & 4 deletions tests/test_console.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ def test_export_html() -> None:
console.print("[b]foo <script> 'test' [link=https://example.org]Click[/link]")
html = console.export_html()
print(repr(html))
expected = '<!DOCTYPE html>\n<html>\n<head>\n<meta charset="UTF-8">\n<style>\n.r1 {font-weight: bold}\n.r2 {color: #ff00ff; text-decoration-color: #ff00ff; font-weight: bold}\n.r3 {color: #008000; text-decoration-color: #008000; font-weight: bold}\nbody {\n color: #000000;\n background-color: #ffffff;\n}\n</style>\n</head>\n<body>\n <pre style="font-family:Menlo,\'DejaVu Sans Mono\',consolas,\'Courier New\',monospace"><code style="font-family:inherit"><span class="r1">foo &lt;</span><span class="r2">script</span><span class="r1">&gt; </span><span class="r3">&#x27;test&#x27;</span><span class="r1"> </span><a class="r1" href="https://example.org">Click</a>\n</code></pre>\n</body>\n</html>\n'
expected = '<!DOCTYPE html>\n<!-- @generated with Rich https://www.textualize.io -->\n<html>\n<head>\n<meta charset="UTF-8">\n<style>\n.r1 {font-weight: bold}\n.r2 {color: #ff00ff; text-decoration-color: #ff00ff; font-weight: bold}\n.r3 {color: #008000; text-decoration-color: #008000; font-weight: bold}\nbody {\n color: #000000;\n background-color: #ffffff;\n}\n</style>\n</head>\n<body>\n <pre style="font-family:Menlo,\'DejaVu Sans Mono\',consolas,\'Courier New\',monospace"><code style="font-family:inherit"><span class="r1">foo &lt;</span><span class="r2">script</span><span class="r1">&gt; </span><span class="r3">&#x27;test&#x27;</span><span class="r1"> </span><a class="r1" href="https://example.org">Click</a>\n</code></pre>\n</body>\n</html>\n'
assert html == expected


Expand All @@ -524,11 +524,11 @@ def test_export_html_inline() -> None:
console.print("[b]foo [link=https://example.org]Click[/link]")
html = console.export_html(inline_styles=True)
print(repr(html))
expected = '<!DOCTYPE html>\n<html>\n<head>\n<meta charset="UTF-8">\n<style>\n\nbody {\n color: #000000;\n background-color: #ffffff;\n}\n</style>\n</head>\n<body>\n <pre style="font-family:Menlo,\'DejaVu Sans Mono\',consolas,\'Courier New\',monospace"><code style="font-family:inherit"><span style="font-weight: bold">foo </span><span style="font-weight: bold"><a href="https://example.org">Click</a></span>\n</code></pre>\n</body>\n</html>\n'
expected = '<!DOCTYPE html>\n<!-- @generated with Rich https://www.textualize.io -->\n<html>\n<head>\n<meta charset="UTF-8">\n<style>\n\nbody {\n color: #000000;\n background-color: #ffffff;\n}\n</style>\n</head>\n<body>\n <pre style="font-family:Menlo,\'DejaVu Sans Mono\',consolas,\'Courier New\',monospace"><code style="font-family:inherit"><span style="font-weight: bold">foo </span><span style="font-weight: bold"><a href="https://example.org">Click</a></span>\n</code></pre>\n</body>\n</html>\n'
assert html == expected


EXPECTED_SVG = '<svg class="rich-terminal" viewBox="0 0 1238 74.4" xmlns="http://www.w3.org/2000/svg">\n <!-- Generated with Rich https://www.textualize.io -->\n <style>\n\n @font-face {\n font-family: "Fira Code";\n src: local("FiraCode-Regular"),\n url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),\n url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");\n font-style: normal;\n font-weight: 400;\n }\n @font-face {\n font-family: "Fira Code";\n src: local("FiraCode-Bold"),\n url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),\n url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");\n font-style: bold;\n font-weight: 700;\n }\n\n .terminal-3526644552-matrix {\n font-family: Fira Code, monospace;\n font-size: 20px;\n line-height: 24.4px;\n font-variant-east-asian: full-width;\n }\n\n .terminal-3526644552-title {\n font-size: 18px;\n font-weight: bold;\n font-family: arial;\n }\n\n .terminal-3526644552-r1 { fill: #608ab1;font-weight: bold }\n.terminal-3526644552-r2 { fill: #c5c8c6 }\n </style>\n\n <defs>\n <clipPath id="terminal-3526644552-clip-terminal">\n <rect x="0" y="0" width="1219.0" height="23.4" />\n </clipPath>\n \n </defs>\n\n <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1236" height="72.4" rx="8"/><text class="terminal-3526644552-title" fill="#c5c8c6" text-anchor="middle" x="618" y="27">Rich</text>\n <g transform="translate(26,22)">\n <circle cx="0" cy="0" r="7" fill="#ff5f57"/>\n <circle cx="22" cy="0" r="7" fill="#febc2e"/>\n <circle cx="44" cy="0" r="7" fill="#28c840"/>\n </g>\n \n <g transform="translate(9, 41)" clip-path="url(#terminal-3526644552-clip-terminal)">\n <rect fill="#cc555a" x="0" y="1.5" width="36.6" height="24.65" shape-rendering="crispEdges"/>\n <g class="terminal-3526644552-matrix">\n <text class="terminal-3526644552-r1" x="0" y="20" textLength="36.6" clip-path="url(#terminal-3526644552-line-0)">foo</text><text class="terminal-3526644552-r2" x="48.8" y="20" textLength="61" clip-path="url(#terminal-3526644552-line-0)">Click</text><text class="terminal-3526644552-r2" x="1220" y="20" textLength="12.2" clip-path="url(#terminal-3526644552-line-0)">\n</text>\n </g>\n </g>\n</svg>\n'
EXPECTED_SVG = '<svg class="rich-terminal" viewBox="0 0 1238 74.4" xmlns="http://www.w3.org/2000/svg">\n <!-- @generated with Rich https://www.textualize.io -->\n <style>\n\n @font-face {\n font-family: "Fira Code";\n src: local("FiraCode-Regular"),\n url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),\n url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");\n font-style: normal;\n font-weight: 400;\n }\n @font-face {\n font-family: "Fira Code";\n src: local("FiraCode-Bold"),\n url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),\n url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");\n font-style: bold;\n font-weight: 700;\n }\n\n .terminal-3526644552-matrix {\n font-family: Fira Code, monospace;\n font-size: 20px;\n line-height: 24.4px;\n font-variant-east-asian: full-width;\n }\n\n .terminal-3526644552-title {\n font-size: 18px;\n font-weight: bold;\n font-family: arial;\n }\n\n .terminal-3526644552-r1 { fill: #608ab1;font-weight: bold }\n.terminal-3526644552-r2 { fill: #c5c8c6 }\n </style>\n\n <defs>\n <clipPath id="terminal-3526644552-clip-terminal">\n <rect x="0" y="0" width="1219.0" height="23.4" />\n </clipPath>\n \n </defs>\n\n <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1236" height="72.4" rx="8"/><text class="terminal-3526644552-title" fill="#c5c8c6" text-anchor="middle" x="618" y="27">Rich</text>\n <g transform="translate(26,22)">\n <circle cx="0" cy="0" r="7" fill="#ff5f57"/>\n <circle cx="22" cy="0" r="7" fill="#febc2e"/>\n <circle cx="44" cy="0" r="7" fill="#28c840"/>\n </g>\n \n <g transform="translate(9, 41)" clip-path="url(#terminal-3526644552-clip-terminal)">\n <rect fill="#cc555a" x="0" y="1.5" width="36.6" height="24.65" shape-rendering="crispEdges"/>\n <g class="terminal-3526644552-matrix">\n <text class="terminal-3526644552-r1" x="0" y="20" textLength="36.6" clip-path="url(#terminal-3526644552-line-0)">foo</text><text class="terminal-3526644552-r2" x="48.8" y="20" textLength="61" clip-path="url(#terminal-3526644552-line-0)">Click</text><text class="terminal-3526644552-r2" x="1220" y="20" textLength="12.2" clip-path="url(#terminal-3526644552-line-0)">\n</text>\n </g>\n </g>\n</svg>\n'


def test_export_svg() -> None:
Expand Down Expand Up @@ -577,7 +577,7 @@ def test_save_text() -> None:


def test_save_html() -> None:
expected = '<!DOCTYPE html>\n<html>\n<head>\n<meta charset="UTF-8">\n<style>\n\nbody {\n color: #000000;\n background-color: #ffffff;\n}\n</style>\n</head>\n<body>\n <pre style="font-family:Menlo,\'DejaVu Sans Mono\',consolas,\'Courier New\',monospace"><code style="font-family:inherit">foo\n</code></pre>\n</body>\n</html>\n'
expected = '<!DOCTYPE html>\n<!-- @generated with Rich https://www.textualize.io -->\n<html>\n<head>\n<meta charset="UTF-8">\n<style>\n\nbody {\n color: #000000;\n background-color: #ffffff;\n}\n</style>\n</head>\n<body>\n <pre style="font-family:Menlo,\'DejaVu Sans Mono\',consolas,\'Courier New\',monospace"><code style="font-family:inherit">foo\n</code></pre>\n</body>\n</html>\n'
console = Console(record=True, width=100)
console.print("foo")
with tempfile.TemporaryDirectory() as path:
Expand Down