Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
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
}
86 changes: 86 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 @@ -54,6 +54,7 @@
"@playwright/test": "1.29.0",
"@rollup/pluginutils": "5.0.2",
"@stoplight/spectral-cli": "6.6.0",
"asciinema-player": "3.0.1",
"eslint": "8.30.0",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-jquery": "1.5.1",
Expand Down
10 changes: 10 additions & 0 deletions web_src/js/asciinema/player.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as AsciinemaPlayer from 'asciinema-player';

export function initAsciinemaPlayer() {
const players = document.getElementsByClassName('asciinema-player-container');
for (const player of players) {
AsciinemaPlayer.create(player.getAttribute('data-asciinema-player-src'), player, {
poster: 'npt:1:0:0',
});
}
}
3 changes: 3 additions & 0 deletions web_src/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ import {initRepoCommentForm, initRepository} from './features/repo-legacy.js';
import {initFormattingReplacements} from './features/formatting.js';
import {initMcaptcha} from './features/mcaptcha.js';
import {initCopyContent} from './features/copycontent.js';
import {initAsciinemaPlayer} from './asciinema/player.js';

// Run time-critical code as soon as possible. This is safe to do because this
// script appears at the end of <body> and rendered HTML is accessible at that point.
Expand Down Expand Up @@ -198,4 +199,6 @@ $(document).ready(() => {
initUserSettings();
initViewedCheckboxListenerFor();
checkAppUrl();

initAsciinemaPlayer();
});
10 changes: 10 additions & 0 deletions web_src/less/_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;
}
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 @@ -36,5 +36,6 @@
@import "_explore";
@import "_review";
@import "_package";
@import "_asciicast";

@import "./helpers.less";