Skip to content

Commit

Permalink
Support asciicast files as new markup (#22448)
Browse files Browse the repository at this point in the history
Support [asciicast
files](https://github.com/asciinema/asciinema/blob/develop/doc/asciicast-v2.md)
as a new markup via
[asciinema-player](https://github.com/asciinema/asciinema-player). For
more on asciinema, see the [introduction](https://asciinema.org/).

So users can use asciinema recorder to generate an asciicast file (or
you can download a sample file from
https://asciinema.org/a/335480.cast?dl=1), then upload it to Gitea and
play it on Gitea.

Snapshots:
<details>

## Upload asciicast files

<img width="1134" alt="image"
src="https://user-images.githubusercontent.com/9418365/212461061-cc2c7181-0e14-4534-af55-1ec60a639fd1.png">

## Open an asciicast file

<img width="1137" alt="image"
src="https://user-images.githubusercontent.com/9418365/212461090-a3b5141f-4894-430d-a2b4-ea257801a0ed.png">

## Play it

<img width="1144" alt="image"
src="https://user-images.githubusercontent.com/9418365/212461157-4e82db69-0e41-471d-928f-ac1fe0737105.png">

## Copy contents from the "video"

<img width="1145" alt="image"
src="https://user-images.githubusercontent.com/9418365/212461286-211612bc-15d6-427a-89a9-6abff5c6a0a5.png">


## View the source

<img width="1140" alt="image"
src="https://user-images.githubusercontent.com/9418365/212461187-05473b2d-ba3d-4072-84a6-4aa1e7d82182.png">


</details>

Known issue:

Don't support the [v1 version asciicast
files](https://github.com/asciinema/asciinema/blob/develop/doc/asciicast-v1.md),
it's a poorly designed version, it does not specify the file extension
and uses `*.json` usually, so it's impossible to recognize the files.

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
  • Loading branch information
3 people committed Jan 18, 2023
1 parent de484e8 commit d9f748a
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 0 deletions.
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"code.gitea.io/gitea/modules/setting"

// register supported doc types
_ "code.gitea.io/gitea/modules/markup/asciicast"
_ "code.gitea.io/gitea/modules/markup/console"
_ "code.gitea.io/gitea/modules/markup/csv"
_ "code.gitea.io/gitea/modules/markup/markdown"
Expand Down
64 changes: 64 additions & 0 deletions modules/markup/asciicast/asciicast.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package asciicast

import (
"fmt"
"io"
"net/url"
"regexp"

"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
)

func init() {
markup.RegisterRenderer(Renderer{})
}

// Renderer implements markup.Renderer for asciicast files.
// See https://github.com/asciinema/asciinema/blob/develop/doc/asciicast-v2.md
type Renderer struct{}

// Name implements markup.Renderer
func (Renderer) Name() string {
return "asciicast"
}

// Extensions implements markup.Renderer
func (Renderer) Extensions() []string {
return []string{".cast"}
}

const (
playerClassName = "asciinema-player-container"
playerSrcAttr = "data-asciinema-player-src"
)

// SanitizerRules implements markup.Renderer
func (Renderer) SanitizerRules() []setting.MarkupSanitizerRule {
return []setting.MarkupSanitizerRule{
{Element: "div", AllowAttr: "class", Regexp: regexp.MustCompile(playerClassName)},
{Element: "div", AllowAttr: playerSrcAttr},
}
}

// Render implements markup.Renderer
func (Renderer) Render(ctx *markup.RenderContext, _ io.Reader, output io.Writer) error {
rawURL := fmt.Sprintf("%s/%s/%s/raw/%s/%s",
setting.AppSubURL,
url.PathEscape(ctx.Metas["user"]),
url.PathEscape(ctx.Metas["repo"]),
ctx.Metas["BranchNameSubURL"],
url.PathEscape(ctx.RelativePath),
)

_, err := io.WriteString(output, fmt.Sprintf(
`<div class="%s" %s="%s"></div>`,
playerClassName,
playerSrcAttr,
rawURL,
))
return err
}
76 changes: 76 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@primer/octicons": "17.10.0",
"@vue/compiler-sfc": "3.2.45",
"add-asset-webpack-plugin": "2.0.1",
"asciinema-player": "3.0.1",
"css-loader": "6.7.3",
"dropzone": "6.0.0-beta.2",
"easymde": "2.18.0",
Expand Down
14 changes: 14 additions & 0 deletions web_src/js/markup/asciicast.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export async function renderAsciinemaPlayer() {
const els = document.querySelectorAll('.asciinema-player-container');
if (!els.length) return;

const player = await import(/* webpackChunkName: "asciinema-player" */'asciinema-player');

for (const el of els) {
player.create(el.getAttribute('data-asciinema-player-src'), el, {
// poster (a preview frame) to display until the playback is started.
// Set it to 1 hour (also means the end if the video is shorter) to make the preview frame show more.
poster: 'npt:1:0:0',
});
}
}
2 changes: 2 additions & 0 deletions web_src/js/markup/content.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import {renderMermaid} from './mermaid.js';
import {renderMath} from './math.js';
import {renderCodeCopy} from './codecopy.js';
import {renderAsciinemaPlayer} from './asciicast.js';
import {initMarkupTasklist} from './tasklist.js';

// code that runs for all markup content
export function initMarkupContent() {
renderMermaid();
renderMath();
renderCodeCopy();
renderAsciinemaPlayer();
}

// code that only runs for comments
Expand Down
4 changes: 4 additions & 0 deletions web_src/less/_repository.less
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,10 @@
pre {
overflow: auto;
}

.asciicast {
padding: 5px !important;
}
}

.sidebar {
Expand Down
1 change: 1 addition & 0 deletions web_src/less/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
@import "./markup/content.less";
@import "./markup/codecopy.less";
@import "./code/linebutton.less";
@import "./markup/asciicast.less";

@import "./chroma/base.less";
@import "./chroma/light.less";
Expand Down
10 changes: 10 additions & 0 deletions web_src/less/markup/asciicast.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@import "../asciinema-player/dist/bundle/asciinema-player.css";

.asciinema-player-container {
width: 100%;
height: auto;
}

.asciinema-terminal {
overflow: hidden !important;
}

0 comments on commit d9f748a

Please sign in to comment.