Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
1346a1b
fix: hold the final SVG frame for the captured EndBuffer duration
phil-scott-78 Jun 6, 2026
6a8f5b7
feat: add vcr.toml config presets, Use/Run/macro sugar, and a vcr mig…
phil-scott-78 Jun 6, 2026
fa43f2f
feat: Phase 2 surface reduction — deprecate dead/contradictory settin…
phil-scott-78 Jun 6, 2026
6190ef7
feat: replace static/fit flags with Mode + Size axes; correct the dep…
phil-scott-78 Jun 6, 2026
53f591e
refactor: remove genuinely-dead settings and commands from the grammar
phil-scott-78 Jun 6, 2026
9eb1abd
feat: browserless static SVG via in-process ConPTY + VT parser (no tt…
phil-scott-78 Jun 6, 2026
0d2705e
feat: extract VcrSharp.Terminal engine + libvterm conformance scorebo…
phil-scott-78 Jun 6, 2026
8d3f4cf
feat(terminal): P1 — rewrite parser to the canonical Williams VT500 s…
phil-scott-78 Jun 6, 2026
56b069b
feat(terminal): P2 — scroll region, line edits, tabs, cursor save/res…
phil-scott-78 Jun 6, 2026
2d944b2
feat(terminal): P4 — DEC modes, alternate screen, real cursor visibility
phil-scott-78 Jun 6, 2026
2b9de03
feat(terminal): P3 — full SGR attribute model, line drawing, combinin…
phil-scott-78 Jun 6, 2026
b709d45
feat(terminal): P5 — content-preserving resize
phil-scott-78 Jun 6, 2026
6fbd644
fix(terminal): HPB/VPB, resize phantom cursor, + harness Perl x-repeat
phil-scott-78 Jun 6, 2026
5ce1ac3
feat(terminal): DECALN + harness screen_text UTF-8 byte decoding
phil-scott-78 Jun 6, 2026
6c0cd20
docs: record P1–P5 build progress and remaining conformance tail
phil-scott-78 Jun 6, 2026
296b564
feat(terminal): P6 (animation) — browserless animated SVG via poll-at…
phil-scott-78 Jun 6, 2026
147ed77
docs: mark P6 animation (browserless animated SVG) as landed
phil-scott-78 Jun 6, 2026
3a262c5
feat(terminal): native tape playback — Type/Key/Wait/Hide over ConPTY…
phil-scott-78 Jun 6, 2026
5d80d66
docs: mark P6 native playback landed; record fallback rules
phil-scott-78 Jun 6, 2026
9019cb1
fix(terminal): native playback parity with the browser path (#2 promp…
phil-scott-78 Jun 6, 2026
d0cec2d
fix(render): integer cell metrics in the browserless path → seamless …
phil-scott-78 Jun 6, 2026
ec336db
feat(terminal): grapheme-cluster width for emoji modifiers, ZWJ, vari…
phil-scott-78 Jun 6, 2026
64b2102
fix(terminal): run interactive PSReadLine setup at shell startup (no …
phil-scott-78 Jun 6, 2026
3d01531
fix(terminal): native interactive prompt parity with the browser ('> ')
phil-scott-78 Jun 6, 2026
507272d
feat(terminal): event-driven capture + key pacing — never miss a frame
phil-scott-78 Jun 6, 2026
593a539
feat(terminal): honor `Set Shell` in the native path via ShellConfigu…
phil-scott-78 Jun 6, 2026
f7e487a
feat(terminal): native GIF/MP4/WebM/PNG — rasterize frames + FFmpeg (…
phil-scott-78 Jun 6, 2026
95340e8
feat(terminal): Unix PTY backend — native browserless path on Linux/m…
phil-scott-78 Jun 6, 2026
fbc2d52
feat(render): SVG honors reverse video (SGR 7) — fg/bg swap parity wi…
phil-scott-78 Jun 7, 2026
43182fe
feat(render): SVG honors dim/faint text (SGR 2)
phil-scott-78 Jun 7, 2026
bd469a3
feat(render): SVG honors strikethrough (SGR 9); unify text-decoration
phil-scott-78 Jun 7, 2026
1e22b86
feat(render): SVG honors overline (SGR 53)
phil-scott-78 Jun 7, 2026
5a65786
feat(render): SVG honors conceal/hidden text (SGR 8)
phil-scott-78 Jun 7, 2026
61999be
samples: SGR text-style sampler (tape + pwsh script) for SVG verifica…
phil-scott-78 Jun 7, 2026
38bb022
fix(terminal): native launch shape keys off Exec, not Type/Key
phil-scott-78 Jun 7, 2026
a7656fe
chore: ignore scratch/local artifacts; drop generated welcome.svg
phil-scott-78 Jun 7, 2026
0cf0885
feat(native): make the in-process PTY/VtScreen path the only backend;…
phil-scott-78 Jun 7, 2026
7c32c69
docs: rewrite README, CLAUDE.md, and docs site for the browserless ba…
phil-scott-78 Jun 7, 2026
3330bb6
chore(cli): drop vestigial Playwright NU5111 suppression
phil-scott-78 Jun 7, 2026
5fdee20
refactor(core, infra): simplify AST construction, method signatures, …
phil-scott-78 Jun 7, 2026
81f8064
perf(svg): slash animated-SVG size on glyph-heavy output
phil-scott-78 Jun 7, 2026
9a3a71d
perf(svg): merge horizontal runs of identical box/block glyphs
phil-scott-78 Jun 7, 2026
d9d49ad
docs: nudge 0.0.35 for pre-rewrite users; refresh docs samples/SVGs
phil-scott-78 Jun 7, 2026
51e52c1
Merge remote-tracking branch 'origin/main' into total-rewrite
phil-scott-78 Jun 7, 2026
231a539
ci: drop Playwright browser install; refresh stale Playwright references
phil-scott-78 Jun 7, 2026
89fd748
ci: bump actions/checkout and setup-dotnet to v5
phil-scott-78 Jun 7, 2026
f96b9dc
refactor(infra): hoist native capture state into a holder object
phil-scott-78 Jun 7, 2026
b58ff86
refactor(terminal): replace `object` locks with `Lock` type for consi…
phil-scott-78 Jun 7, 2026
585de3c
refactor: drop Native* prefix now that the native path is the only path
phil-scott-78 Jun 7, 2026
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
4 changes: 2 additions & 2 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- name: Install .NET
uses: actions/setup-dotnet@v4
uses: actions/setup-dotnet@v5
with:
global-json-file: global.json

Expand Down
5 changes: 1 addition & 4 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

Expand All @@ -28,9 +28,6 @@ jobs:
- name: Build
run: dotnet build -c Debug

- name: Install Playwright Browsers
run: pwsh tests/VcrSharp.Integration.Tests/bin/Debug/net10.0/playwright.ps1 install chromium --no-shell

- name: Test (Debug)
run: dotnet test -c Debug --no-build

Expand Down
16 changes: 15 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -484,4 +484,18 @@ $RECYCLE.BIN/
*.swp

# dotnet-release artifacts
artifacts-dotnet-releaser/
artifacts-dotnet-releaser/

# Scratch / native demo recordings (local only)
.native-demo/
scratch/

# Claude Code local state (runtime + machine-local settings)
.claude/settings.local.json
.claude/scheduled_tasks.lock

# Generated sample output (samples/welcome.tape -> welcome.svg)
/welcome.svg

# Pennington static-site build output (docs/VcrSharp.Docs `dotnet run -- build`)
docs/VcrSharp.Docs/output/
397 changes: 192 additions & 205 deletions CLAUDE.md

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@ dotnet test
```
VcrSharp/
├── src/
│ ├── VcrSharp.Core/ # Core parsing and model
│ ├── VcrSharp.Infrastructure/ # Playwright integration
│ └── VcrSharp.Cli/ # CLI tool
│ ├── VcrSharp.Core/ # Parsing, AST, config, themes, grid DTOs
│ ├── VcrSharp.Terminal/ # VtScreen — from-scratch VT500 engine
│ ├── VcrSharp.Infrastructure/ # PTY backends, recording session, renderers
│ └── VcrSharp.Cli/ # CLI tool
├── tests/
│ ├── VcrSharp.Core.Tests/
│ ├── VcrSharp.Infrastructure.Tests/
│ └── VcrSharp.Cli.Tests/
└── samples/ # Example .tape files
│ └── VcrSharp.Terminal.Tests/ # VtScreen unit + libvterm conformance corpus
└── samples/ # Example .tape files
```

## Code Style
Expand Down
77 changes: 45 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,46 @@
> recorder, please use [VHS](https://github.com/charmbracelet/vhs) instead. VcrSharp is experimental and should be
> considered alpha quality.

A .NET terminal recorder that turns `.tape` files into GIFs and videos. Write your terminal demos as code, then render
them to video.
A .NET terminal recorder that turns `.tape` scripts into GIFs, videos, and SVGs. Write your terminal demos as code, then
render them to GIF, MP4, WebM, PNG, or (animated/static) SVG.

VCR# is **browserless**. It drives a real shell over an in-process pseudo-terminal (ConPTY on Windows, a Unix PTY on
Linux/macOS) and renders the output with its own VT500 terminal engine — **no ttyd, no Chromium, no Playwright**. SVG and
PNG output need no external binaries at all.

![VCR Install Demo](docs/VcrSharp.Docs/Content/vcr-install.svg)

## Installation

VCR# itself ships as a .NET global tool, but it drives a real terminal under the hood, so two extra binaries need to be
on your `PATH`:

- **[ttyd](https://github.com/tsl0922/ttyd)** (>= 1.7.2) — the terminal server VCR# scripts against.
- **[FFmpeg](https://ffmpeg.org/)** — used to encode GIF / MP4 / WebM output.

| OS | Install line |
|---------|---------------------------------------------|
| Windows | `choco install ttyd ffmpeg` |
| macOS | `brew install ttyd ffmpeg` |
| Linux | `sudo apt install ttyd ffmpeg` |

Then install VCR# itself:
VCR# ships as a .NET global tool:

```bash
dotnet tool install --global vcr
```

Verify everything is wired up (`vcr themes` lists the built-in themes, confirming VCR# runs):
> **Need the old behavior?** VCR# was rewritten substantially after `0.0.35`. If you depend on the pre-rewrite
> behavior and aren't ready to migrate, pin that version:
> ```bash
> dotnet tool install --global vcr --version 0.0.35
> ```

That's the whole install for SVG and PNG output. If you want to encode **GIF, MP4, or WebM**, also put
[FFmpeg](https://ffmpeg.org/) on your `PATH`:

| OS | Install FFmpeg (video output only) |
|---------|------------------------------------|
| Windows | `choco install ffmpeg` |
| macOS | `brew install ffmpeg` |
| Linux | `sudo apt install ffmpeg` |

**Requirements:** .NET 10. FFmpeg is required only for GIF/MP4/WebM. Raster output (GIF/MP4/WebM/PNG) also uses a
monospace font installed on your system — usually already present (Consolas/Cascadia on Windows, DejaVu Sans Mono on
Linux); SVG output needs none.

Verify it runs (`vcr themes` lists the built-in themes):

```bash
vcr themes
ttyd --version
ffmpeg -version
```

The full walkthrough lives in the [Getting Started tutorial](https://phil-scott-78.github.io/vcr/tutorials/getting-started.html).
Expand All @@ -45,7 +54,7 @@ The full walkthrough lives in the [Getting Started tutorial](https://phil-scott-
Create a file called `demo.tape`:

```tape
Output demo.gif
Output demo.svg

Set Cols 80
Set Rows 20
Expand All @@ -56,37 +65,41 @@ Enter
Sleep 1s
```

Then record it:
Then record it (SVG output needs no extra tools):

```bash
vcr demo.tape
```

Change `Output demo.svg` to `demo.gif` to render a GIF instead (requires FFmpeg).

## CLI at a glance

| Command | What it does |
|------------------------|----------------------------------------------------------------|
| `vcr <tape>` | Record a tape file to its declared `Output` target(s). |
| `vcr record [tape]` | Record a live shell session into a `.tape` file as you type — works in any shell. |
| `vcr validate <tape>` | Parse a tape file and report syntax errors without recording. |
| `vcr themes` | List the 10 built-in themes with their background/foreground colors. |
| `vcr snap <command>` | One-shot SVG screenshot of running `<command>` — no tape file. |
| `vcr capture <command>`| Animated SVG of `<command>` start to finish — no tape file. |
| Command | What it does |
|-------------------------|-------------------------------------------------------------------------------|
| `vcr <tape>` | Record a tape file to its declared `Output` target(s), in-process (no browser). |
| `vcr validate <tape>` | Parse a tape file and report syntax errors without recording. |
| `vcr themes` | List the built-in themes with their background/foreground colors. |
| `vcr snap <command>` | One-shot static SVG screenshot of `<command>`'s final output — no tape file. |
| `vcr capture <command>` | Animated SVG of `<command>` start to finish — no tape file. |
| `vcr record [tape]` | Record a live shell session into a `.tape` file as you type — works in any shell. |
| `vcr migrate <dir>` | Mine a directory of tapes into a shared `vcr.toml` preset (dry run by default). |

## Documentation

Full docs, tutorials, and reference: **https://phil-scott-78.github.io/vcr/**

- [Getting Started Tutorial](https://phil-scott-78.github.io/vcr/tutorials/getting-started.html)
- [Command Reference](https://phil-scott-78.github.io/vcr/reference/tape-syntax.html)
- [Configuration Guide](https://phil-scott-78.github.io/vcr/how-to/cli-overrides.html)
- [Tape Syntax Reference](https://phil-scott-78.github.io/vcr/reference/tape-syntax.html)
- [Configuration Options](https://phil-scott-78.github.io/vcr/reference/configuration-options.html)
- Sample tape files in [`samples/`](samples/)

## Attribution

This project is heavily inspired by [VHS](https://github.com/charmbracelet/vhs) by [Charm Bracelet](https://charm.sh/).
VcrSharp adds better Windows support, the ability to execute real commands via the `Exec` command, and an interactive
`record` mode that works across shells (VHS's is bash-only) — but VHS is still much more feature rich.
VcrSharp adds first-class Windows support, a fully browserless rendering path (its own VT500 terminal engine, no ttyd or
Chromium), the ability to execute real commands via the `Exec` command, and an interactive `record` mode that works
across shells (VHS's is bash-only) — but VHS is still much more feature rich.

## License

Expand Down
45 changes: 30 additions & 15 deletions VcrSharp.sln
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VcrSharp.Core.Tests", "tests\VcrSharp.Core.Tests\VcrSharp.Core.Tests.csproj", "{6C3D8455-565E-4385-BAD2-13D9790088E5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VcrSharp.Integration.Tests", "tests\VcrSharp.Integration.Tests\VcrSharp.Integration.Tests.csproj", "{7197AF67-1860-4B2A-A7E6-BCD08EECDFD0}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{D5C68820-B4D8-449F-BFFD-8A342A1D0271}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VcrSharp.Docs", "docs\VcrSharp.Docs\VcrSharp.Docs.csproj", "{8D116118-EA66-41E5-8CD0-2C4D2813DAB2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VcrSharp.Terminal", "src\VcrSharp.Terminal\VcrSharp.Terminal.csproj", "{536115C6-F9FB-4CF3-B058-498188BB6B69}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VcrSharp.Terminal.Tests", "tests\VcrSharp.Terminal.Tests\VcrSharp.Terminal.Tests.csproj", "{1814D8F8-4D06-42CD-8701-7D43C4377C55}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -79,18 +81,6 @@ Global
{6C3D8455-565E-4385-BAD2-13D9790088E5}.Release|x64.Build.0 = Release|Any CPU
{6C3D8455-565E-4385-BAD2-13D9790088E5}.Release|x86.ActiveCfg = Release|Any CPU
{6C3D8455-565E-4385-BAD2-13D9790088E5}.Release|x86.Build.0 = Release|Any CPU
{7197AF67-1860-4B2A-A7E6-BCD08EECDFD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7197AF67-1860-4B2A-A7E6-BCD08EECDFD0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7197AF67-1860-4B2A-A7E6-BCD08EECDFD0}.Debug|x64.ActiveCfg = Debug|Any CPU
{7197AF67-1860-4B2A-A7E6-BCD08EECDFD0}.Debug|x64.Build.0 = Debug|Any CPU
{7197AF67-1860-4B2A-A7E6-BCD08EECDFD0}.Debug|x86.ActiveCfg = Debug|Any CPU
{7197AF67-1860-4B2A-A7E6-BCD08EECDFD0}.Debug|x86.Build.0 = Debug|Any CPU
{7197AF67-1860-4B2A-A7E6-BCD08EECDFD0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7197AF67-1860-4B2A-A7E6-BCD08EECDFD0}.Release|Any CPU.Build.0 = Release|Any CPU
{7197AF67-1860-4B2A-A7E6-BCD08EECDFD0}.Release|x64.ActiveCfg = Release|Any CPU
{7197AF67-1860-4B2A-A7E6-BCD08EECDFD0}.Release|x64.Build.0 = Release|Any CPU
{7197AF67-1860-4B2A-A7E6-BCD08EECDFD0}.Release|x86.ActiveCfg = Release|Any CPU
{7197AF67-1860-4B2A-A7E6-BCD08EECDFD0}.Release|x86.Build.0 = Release|Any CPU
{8D116118-EA66-41E5-8CD0-2C4D2813DAB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8D116118-EA66-41E5-8CD0-2C4D2813DAB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D116118-EA66-41E5-8CD0-2C4D2813DAB2}.Debug|x64.ActiveCfg = Debug|Any CPU
Expand All @@ -103,6 +93,30 @@ Global
{8D116118-EA66-41E5-8CD0-2C4D2813DAB2}.Release|x64.Build.0 = Release|Any CPU
{8D116118-EA66-41E5-8CD0-2C4D2813DAB2}.Release|x86.ActiveCfg = Release|Any CPU
{8D116118-EA66-41E5-8CD0-2C4D2813DAB2}.Release|x86.Build.0 = Release|Any CPU
{536115C6-F9FB-4CF3-B058-498188BB6B69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{536115C6-F9FB-4CF3-B058-498188BB6B69}.Debug|Any CPU.Build.0 = Debug|Any CPU
{536115C6-F9FB-4CF3-B058-498188BB6B69}.Debug|x64.ActiveCfg = Debug|Any CPU
{536115C6-F9FB-4CF3-B058-498188BB6B69}.Debug|x64.Build.0 = Debug|Any CPU
{536115C6-F9FB-4CF3-B058-498188BB6B69}.Debug|x86.ActiveCfg = Debug|Any CPU
{536115C6-F9FB-4CF3-B058-498188BB6B69}.Debug|x86.Build.0 = Debug|Any CPU
{536115C6-F9FB-4CF3-B058-498188BB6B69}.Release|Any CPU.ActiveCfg = Release|Any CPU
{536115C6-F9FB-4CF3-B058-498188BB6B69}.Release|Any CPU.Build.0 = Release|Any CPU
{536115C6-F9FB-4CF3-B058-498188BB6B69}.Release|x64.ActiveCfg = Release|Any CPU
{536115C6-F9FB-4CF3-B058-498188BB6B69}.Release|x64.Build.0 = Release|Any CPU
{536115C6-F9FB-4CF3-B058-498188BB6B69}.Release|x86.ActiveCfg = Release|Any CPU
{536115C6-F9FB-4CF3-B058-498188BB6B69}.Release|x86.Build.0 = Release|Any CPU
{1814D8F8-4D06-42CD-8701-7D43C4377C55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1814D8F8-4D06-42CD-8701-7D43C4377C55}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1814D8F8-4D06-42CD-8701-7D43C4377C55}.Debug|x64.ActiveCfg = Debug|Any CPU
{1814D8F8-4D06-42CD-8701-7D43C4377C55}.Debug|x64.Build.0 = Debug|Any CPU
{1814D8F8-4D06-42CD-8701-7D43C4377C55}.Debug|x86.ActiveCfg = Debug|Any CPU
{1814D8F8-4D06-42CD-8701-7D43C4377C55}.Debug|x86.Build.0 = Debug|Any CPU
{1814D8F8-4D06-42CD-8701-7D43C4377C55}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1814D8F8-4D06-42CD-8701-7D43C4377C55}.Release|Any CPU.Build.0 = Release|Any CPU
{1814D8F8-4D06-42CD-8701-7D43C4377C55}.Release|x64.ActiveCfg = Release|Any CPU
{1814D8F8-4D06-42CD-8701-7D43C4377C55}.Release|x64.Build.0 = Release|Any CPU
{1814D8F8-4D06-42CD-8701-7D43C4377C55}.Release|x86.ActiveCfg = Release|Any CPU
{1814D8F8-4D06-42CD-8701-7D43C4377C55}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -112,7 +126,8 @@ Global
{C71CB170-371B-48DF-8836-F97ECA1B0DFB} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{E672E96A-8269-4434-ACB8-0E585398A1ED} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{6C3D8455-565E-4385-BAD2-13D9790088E5} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
{7197AF67-1860-4B2A-A7E6-BCD08EECDFD0} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
{8D116118-EA66-41E5-8CD0-2C4D2813DAB2} = {D5C68820-B4D8-449F-BFFD-8A342A1D0271}
{536115C6-F9FB-4CF3-B058-498188BB6B69} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{1814D8F8-4D06-42CD-8701-7D43C4377C55} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
EndGlobalSection
EndGlobal
2 changes: 1 addition & 1 deletion docs/VcrSharp.Docs/Content/demos/exec-real-command.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading