From b795c6c9e771fa5a4038b55a6e24955b8973ae55 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Fri, 13 Jan 2023 17:03:43 +0800 Subject: [PATCH 01/14] feat: add markup asciicast --- main.go | 1 + modules/markup/asciicast/asciicast.go | 64 +++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 modules/markup/asciicast/asciicast.go diff --git a/main.go b/main.go index 070e9857d08c0..4b183a768609d 100644 --- a/main.go +++ b/main.go @@ -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" diff --git a/modules/markup/asciicast/asciicast.go b/modules/markup/asciicast/asciicast.go new file mode 100644 index 0000000000000..37df7904e4fb7 --- /dev/null +++ b/modules/markup/asciicast/asciicast.go @@ -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 = "asciicast-player-container" + playerSrcAttr = "data-asciicast-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( + `
`, + playerClassName, + playerSrcAttr, + rawURL, + )) + return err +} From 9f81e08de168008235021e0a78fcc774ad062524 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Fri, 13 Jan 2023 17:08:51 +0800 Subject: [PATCH 02/14] chore: install asciinema-player --- package-lock.json | 86 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 87 insertions(+) diff --git a/package-lock.json b/package-lock.json index a301dcddb301e..5cbe8ece85bfd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", @@ -197,6 +198,18 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/runtime": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", + "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@braintree/sanitize-url": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.2.tgz", @@ -2094,6 +2107,16 @@ "printable-characters": "^1.0.42" } }, + "node_modules/asciinema-player": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/asciinema-player/-/asciinema-player-3.0.1.tgz", + "integrity": "sha512-plm/C/MhOtZWysrfcT/rzxOuu8vxvvDSvF50pqZS6KpJUDmATedAhO54zktbE/g7RiaaYfzgX8xjRhlQdgISwA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.15.4", + "solid-js": "^1.3.0" + } + }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -7754,6 +7777,12 @@ "node": ">=8" } }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "dev": true + }, "node_modules/regexp-tree": { "version": "0.1.24", "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz", @@ -8249,6 +8278,21 @@ "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", "dev": true }, + "node_modules/solid-js": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.6.9.tgz", + "integrity": "sha512-kV3fMmm+1C2J95c8eDOPKGfZHnuAkHUBLG4hX1Xu08bXeAIPqmxuz/QdH3B8SIdTp3EatBVIyA6RCes3hrGzpg==", + "dev": true, + "dependencies": { + "csstype": "^3.1.0" + } + }, + "node_modules/solid-js/node_modules/csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==", + "dev": true + }, "node_modules/sortablejs": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz", @@ -10159,6 +10203,15 @@ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz", "integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==" }, + "@babel/runtime": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", + "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.11" + } + }, "@braintree/sanitize-url": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.2.tgz", @@ -11525,6 +11578,16 @@ "printable-characters": "^1.0.42" } }, + "asciinema-player": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/asciinema-player/-/asciinema-player-3.0.1.tgz", + "integrity": "sha512-plm/C/MhOtZWysrfcT/rzxOuu8vxvvDSvF50pqZS6KpJUDmATedAhO54zktbE/g7RiaaYfzgX8xjRhlQdgISwA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.15.4", + "solid-js": "^1.3.0" + } + }, "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -15606,6 +15669,12 @@ "strip-indent": "^3.0.0" } }, + "regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "dev": true + }, "regexp-tree": { "version": "0.1.24", "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz", @@ -15960,6 +16029,23 @@ "socks": "^2.3.3" } }, + "solid-js": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.6.9.tgz", + "integrity": "sha512-kV3fMmm+1C2J95c8eDOPKGfZHnuAkHUBLG4hX1Xu08bXeAIPqmxuz/QdH3B8SIdTp3EatBVIyA6RCes3hrGzpg==", + "dev": true, + "requires": { + "csstype": "^3.1.0" + }, + "dependencies": { + "csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==", + "dev": true + } + } + }, "sortablejs": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz", diff --git a/package.json b/package.json index 229d4f1aa90a3..b820bcb505995 100644 --- a/package.json +++ b/package.json @@ -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", From c7b31a1a5451cedc0e6495a4ad963ce032c2193e Mon Sep 17 00:00:00 2001 From: Jason Song Date: Fri, 13 Jan 2023 17:20:35 +0800 Subject: [PATCH 03/14] feat: init asciinema-player --- modules/markup/asciicast/asciicast.go | 4 ++-- web_src/js/asciinema/player.js | 14 ++++++++++++++ web_src/js/index.js | 3 +++ 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 web_src/js/asciinema/player.js diff --git a/modules/markup/asciicast/asciicast.go b/modules/markup/asciicast/asciicast.go index 37df7904e4fb7..06780623403a4 100644 --- a/modules/markup/asciicast/asciicast.go +++ b/modules/markup/asciicast/asciicast.go @@ -32,8 +32,8 @@ func (Renderer) Extensions() []string { } const ( - playerClassName = "asciicast-player-container" - playerSrcAttr = "data-asciicast-player-src" + playerClassName = "asciinema-player-container" + playerSrcAttr = "data-asciinema-player-src" ) // SanitizerRules implements markup.Renderer diff --git a/web_src/js/asciinema/player.js b/web_src/js/asciinema/player.js new file mode 100644 index 0000000000000..35247bfb442de --- /dev/null +++ b/web_src/js/asciinema/player.js @@ -0,0 +1,14 @@ +import * as AsciinemaPlayer from 'asciinema-player'; + +export function initAsciinemaPlayer() { + const players = document.getElementsByClassName('asciinema-player-container'); + console.log('start'); + for (const player of players) { + console.log('init'); + AsciinemaPlayer.create(player.getAttribute('data-asciinema-player-src'), player, { + fit: 'both', + preload: true, + poster: 'npt:100:0:0', + }); + } +} diff --git a/web_src/js/index.js b/web_src/js/index.js index a866184203fd6..06626e34cd29b 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -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 and rendered HTML is accessible at that point. @@ -198,4 +199,6 @@ $(document).ready(() => { initUserSettings(); initViewedCheckboxListenerFor(); checkAppUrl(); + + initAsciinemaPlayer(); }); From a76bfed2149afa958579743ff9c11d30a1b68e61 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Sat, 14 Jan 2023 10:58:20 +0800 Subject: [PATCH 04/14] fix: import css --- web_src/less/_asciicast.less | 10 ++++++++++ web_src/less/_repository.less | 4 ++++ web_src/less/index.less | 1 + 3 files changed, 15 insertions(+) create mode 100644 web_src/less/_asciicast.less diff --git a/web_src/less/_asciicast.less b/web_src/less/_asciicast.less new file mode 100644 index 0000000000000..4df4fc356a4d1 --- /dev/null +++ b/web_src/less/_asciicast.less @@ -0,0 +1,10 @@ +@import "asciinema-player/dist/bundle/asciinema-player.css"; + +.asciinema-player-container { + width: 100%; + height: 600px; +} + +.asciinema-terminal { + overflow: hidden !important; +} diff --git a/web_src/less/_repository.less b/web_src/less/_repository.less index 646cf4e60e28a..4bcaf8dd040f8 100644 --- a/web_src/less/_repository.less +++ b/web_src/less/_repository.less @@ -470,6 +470,10 @@ pre { overflow: auto; } + + .asciicast { + padding: 5px !important; + } } .sidebar { diff --git a/web_src/less/index.less b/web_src/less/index.less index 2d670ac2d5d34..f7e3e0ef792d8 100644 --- a/web_src/less/index.less +++ b/web_src/less/index.less @@ -36,5 +36,6 @@ @import "_explore"; @import "_review"; @import "_package"; +@import "_asciicast"; @import "./helpers.less"; From 9530aae0b05e5938588630d63a54e3f145317957 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Sat, 14 Jan 2023 11:21:50 +0800 Subject: [PATCH 05/14] feat: extractHeader --- modules/markup/asciicast/asciicast.go | 20 +++++++++++-- modules/markup/asciicast/header.go | 43 +++++++++++++++++++++++++++ web_src/less/_asciicast.less | 1 - 3 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 modules/markup/asciicast/header.go diff --git a/modules/markup/asciicast/asciicast.go b/modules/markup/asciicast/asciicast.go index 06780623403a4..30bffd2b210e8 100644 --- a/modules/markup/asciicast/asciicast.go +++ b/modules/markup/asciicast/asciicast.go @@ -4,11 +4,13 @@ package asciicast import ( + "bufio" "fmt" "io" "net/url" "regexp" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/setting" ) @@ -40,12 +42,20 @@ const ( func (Renderer) SanitizerRules() []setting.MarkupSanitizerRule { return []setting.MarkupSanitizerRule{ {Element: "div", AllowAttr: "class", Regexp: regexp.MustCompile(playerClassName)}, + {Element: "div", AllowAttr: "style"}, {Element: "div", AllowAttr: playerSrcAttr}, } } // Render implements markup.Renderer -func (Renderer) Render(ctx *markup.RenderContext, _ io.Reader, output io.Writer) error { +func (Renderer) Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error { + var h *header + if firstLine, err := bufio.NewReader(input).ReadBytes('\n'); err != nil { + return err + } else if h, err = extractHeader(firstLine); err != nil { + log.Warn("extract header from %s: %v", ctx.RelativePath, err) + } + rawURL := fmt.Sprintf("%s/%s/%s/raw/%s/%s", setting.AppSubURL, url.PathEscape(ctx.Metas["user"]), @@ -54,9 +64,15 @@ func (Renderer) Render(ctx *markup.RenderContext, _ io.Reader, output io.Writer) url.PathEscape(ctx.RelativePath), ) + style := "" + if h != nil { + style = fmt.Sprintf("aspect-ratio: %d / %d", h.Width, h.Height) + } + _, err := io.WriteString(output, fmt.Sprintf( - `
`, + `
`, playerClassName, + style, playerSrcAttr, rawURL, )) diff --git a/modules/markup/asciicast/header.go b/modules/markup/asciicast/header.go new file mode 100644 index 0000000000000..cfcdce1d9733d --- /dev/null +++ b/modules/markup/asciicast/header.go @@ -0,0 +1,43 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package asciicast + +import ( + "fmt" + + "code.gitea.io/gitea/modules/json" +) + +type header struct { + // Required header attributes: + Version int `json:"version"` + Width int `json:"width"` + Height int `json:"height"` + + // Optional header attributes: + Timestamp int `json:"timestamp"` + Duration float64 `json:"duration"` + IdleTimeLimit float64 `json:"idle_time_limit"` + Command string `json:"command"` + Title string `json:"title"` + Env map[string]string `json:"env"` + Theme string `json:"theme"` +} + +func extractHeader(data []byte) (*header, error) { + h := &header{} + if err := json.Unmarshal(data, h); err != nil { + return nil, fmt.Errorf("json unmarshal: %w", err) + } + if h.Version != 2 { + return nil, fmt.Errorf("unknown version: %v", h.Version) + } + if h.Width <= 0 { + return nil, fmt.Errorf("invalid width: %v", h.Width) + } + if h.Height <= 0 { + return nil, fmt.Errorf("invalid height: %v", h.Height) + } + return h, nil +} diff --git a/web_src/less/_asciicast.less b/web_src/less/_asciicast.less index 4df4fc356a4d1..21bbac80da592 100644 --- a/web_src/less/_asciicast.less +++ b/web_src/less/_asciicast.less @@ -2,7 +2,6 @@ .asciinema-player-container { width: 100%; - height: 600px; } .asciinema-terminal { From 1c613dc8aca7e5039623e97849a600a731b7bf46 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Sat, 14 Jan 2023 11:22:01 +0800 Subject: [PATCH 06/14] Revert "feat: extractHeader" This reverts commit 9530aae0b05e5938588630d63a54e3f145317957. --- modules/markup/asciicast/asciicast.go | 20 ++----------- modules/markup/asciicast/header.go | 43 --------------------------- web_src/less/_asciicast.less | 1 + 3 files changed, 3 insertions(+), 61 deletions(-) delete mode 100644 modules/markup/asciicast/header.go diff --git a/modules/markup/asciicast/asciicast.go b/modules/markup/asciicast/asciicast.go index 30bffd2b210e8..06780623403a4 100644 --- a/modules/markup/asciicast/asciicast.go +++ b/modules/markup/asciicast/asciicast.go @@ -4,13 +4,11 @@ package asciicast import ( - "bufio" "fmt" "io" "net/url" "regexp" - "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/setting" ) @@ -42,20 +40,12 @@ const ( func (Renderer) SanitizerRules() []setting.MarkupSanitizerRule { return []setting.MarkupSanitizerRule{ {Element: "div", AllowAttr: "class", Regexp: regexp.MustCompile(playerClassName)}, - {Element: "div", AllowAttr: "style"}, {Element: "div", AllowAttr: playerSrcAttr}, } } // Render implements markup.Renderer -func (Renderer) Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error { - var h *header - if firstLine, err := bufio.NewReader(input).ReadBytes('\n'); err != nil { - return err - } else if h, err = extractHeader(firstLine); err != nil { - log.Warn("extract header from %s: %v", ctx.RelativePath, err) - } - +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"]), @@ -64,15 +54,9 @@ func (Renderer) Render(ctx *markup.RenderContext, input io.Reader, output io.Wri url.PathEscape(ctx.RelativePath), ) - style := "" - if h != nil { - style = fmt.Sprintf("aspect-ratio: %d / %d", h.Width, h.Height) - } - _, err := io.WriteString(output, fmt.Sprintf( - `
`, + `
`, playerClassName, - style, playerSrcAttr, rawURL, )) diff --git a/modules/markup/asciicast/header.go b/modules/markup/asciicast/header.go deleted file mode 100644 index cfcdce1d9733d..0000000000000 --- a/modules/markup/asciicast/header.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2023 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package asciicast - -import ( - "fmt" - - "code.gitea.io/gitea/modules/json" -) - -type header struct { - // Required header attributes: - Version int `json:"version"` - Width int `json:"width"` - Height int `json:"height"` - - // Optional header attributes: - Timestamp int `json:"timestamp"` - Duration float64 `json:"duration"` - IdleTimeLimit float64 `json:"idle_time_limit"` - Command string `json:"command"` - Title string `json:"title"` - Env map[string]string `json:"env"` - Theme string `json:"theme"` -} - -func extractHeader(data []byte) (*header, error) { - h := &header{} - if err := json.Unmarshal(data, h); err != nil { - return nil, fmt.Errorf("json unmarshal: %w", err) - } - if h.Version != 2 { - return nil, fmt.Errorf("unknown version: %v", h.Version) - } - if h.Width <= 0 { - return nil, fmt.Errorf("invalid width: %v", h.Width) - } - if h.Height <= 0 { - return nil, fmt.Errorf("invalid height: %v", h.Height) - } - return h, nil -} diff --git a/web_src/less/_asciicast.less b/web_src/less/_asciicast.less index 21bbac80da592..4df4fc356a4d1 100644 --- a/web_src/less/_asciicast.less +++ b/web_src/less/_asciicast.less @@ -2,6 +2,7 @@ .asciinema-player-container { width: 100%; + height: 600px; } .asciinema-terminal { From ca060fc45379d8b60821831a12d042569fc9322c Mon Sep 17 00:00:00 2001 From: Jason Song Date: Sat, 14 Jan 2023 14:52:22 +0800 Subject: [PATCH 07/14] fix: style --- web_src/js/asciinema/player.js | 6 +----- web_src/less/_asciicast.less | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/web_src/js/asciinema/player.js b/web_src/js/asciinema/player.js index 35247bfb442de..80d8b35e66531 100644 --- a/web_src/js/asciinema/player.js +++ b/web_src/js/asciinema/player.js @@ -2,13 +2,9 @@ import * as AsciinemaPlayer from 'asciinema-player'; export function initAsciinemaPlayer() { const players = document.getElementsByClassName('asciinema-player-container'); - console.log('start'); for (const player of players) { - console.log('init'); AsciinemaPlayer.create(player.getAttribute('data-asciinema-player-src'), player, { - fit: 'both', - preload: true, - poster: 'npt:100:0:0', + poster: 'npt:1:0:0', }); } } diff --git a/web_src/less/_asciicast.less b/web_src/less/_asciicast.less index 4df4fc356a4d1..c6c4f6b8276fd 100644 --- a/web_src/less/_asciicast.less +++ b/web_src/less/_asciicast.less @@ -2,7 +2,7 @@ .asciinema-player-container { width: 100%; - height: 600px; + height: auto; } .asciinema-terminal { From 662aad59c58b802fcc8fbaa07d5e822e68c0feaf Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 16 Jan 2023 21:07:30 +0800 Subject: [PATCH 08/14] chore: move files --- web_src/js/index.js | 2 +- web_src/js/{asciinema/player.js => markup/asciinema.js} | 0 web_src/less/index.less | 2 +- web_src/less/{_asciicast.less => markup/asciicast.less} | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename web_src/js/{asciinema/player.js => markup/asciinema.js} (100%) rename web_src/less/{_asciicast.less => markup/asciicast.less} (65%) diff --git a/web_src/js/index.js b/web_src/js/index.js index 06626e34cd29b..79b787a4bca16 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -90,7 +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'; +import {initAsciinemaPlayer} from './markup/asciinema.js'; // Run time-critical code as soon as possible. This is safe to do because this // script appears at the end of and rendered HTML is accessible at that point. diff --git a/web_src/js/asciinema/player.js b/web_src/js/markup/asciinema.js similarity index 100% rename from web_src/js/asciinema/player.js rename to web_src/js/markup/asciinema.js diff --git a/web_src/less/index.less b/web_src/less/index.less index f7e3e0ef792d8..3e80da180ce77 100644 --- a/web_src/less/index.less +++ b/web_src/less/index.less @@ -13,6 +13,7 @@ @import "./markup/content.less"; @import "./markup/codecopy.less"; @import "./code/linebutton.less"; +@import "./markup/asciicast"; @import "./chroma/base.less"; @import "./chroma/light.less"; @@ -36,6 +37,5 @@ @import "_explore"; @import "_review"; @import "_package"; -@import "_asciicast"; @import "./helpers.less"; diff --git a/web_src/less/_asciicast.less b/web_src/less/markup/asciicast.less similarity index 65% rename from web_src/less/_asciicast.less rename to web_src/less/markup/asciicast.less index c6c4f6b8276fd..468f0b4f3fabf 100644 --- a/web_src/less/_asciicast.less +++ b/web_src/less/markup/asciicast.less @@ -1,4 +1,4 @@ -@import "asciinema-player/dist/bundle/asciinema-player.css"; +@import "../asciinema-player/dist/bundle/asciinema-player.css"; .asciinema-player-container { width: 100%; From 87f8502036c7ec86347770a90fd46cf1a4080348 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Tue, 17 Jan 2023 10:10:21 +0800 Subject: [PATCH 09/14] fix: await import --- web_src/js/index.js | 3 --- web_src/js/markup/asciinema.js | 12 +++++++----- web_src/js/markup/content.js | 2 ++ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/web_src/js/index.js b/web_src/js/index.js index 79b787a4bca16..a866184203fd6 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -90,7 +90,6 @@ 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 './markup/asciinema.js'; // Run time-critical code as soon as possible. This is safe to do because this // script appears at the end of and rendered HTML is accessible at that point. @@ -199,6 +198,4 @@ $(document).ready(() => { initUserSettings(); initViewedCheckboxListenerFor(); checkAppUrl(); - - initAsciinemaPlayer(); }); diff --git a/web_src/js/markup/asciinema.js b/web_src/js/markup/asciinema.js index 80d8b35e66531..7404cabbfac1e 100644 --- a/web_src/js/markup/asciinema.js +++ b/web_src/js/markup/asciinema.js @@ -1,9 +1,11 @@ -import * as AsciinemaPlayer from 'asciinema-player'; +export async function renderAsciinemaPlayer() { + const els = document.querySelectorAll('.asciinema-player-container'); + if (!els.length) return; -export function initAsciinemaPlayer() { - const players = document.getElementsByClassName('asciinema-player-container'); - for (const player of players) { - AsciinemaPlayer.create(player.getAttribute('data-asciinema-player-src'), player, { + const player = await import(/* webpackChunkName: "asciinema" */'asciinema-player'); + + for (const el of els) { + player.create(el.getAttribute('data-asciinema-player-src'), el, { poster: 'npt:1:0:0', }); } diff --git a/web_src/js/markup/content.js b/web_src/js/markup/content.js index 319c229385a3d..005ffc577a4af 100644 --- a/web_src/js/markup/content.js +++ b/web_src/js/markup/content.js @@ -1,6 +1,7 @@ import {renderMermaid} from './mermaid.js'; import {renderMath} from './math.js'; import {renderCodeCopy} from './codecopy.js'; +import {renderAsciinemaPlayer} from './asciinema.js'; import {initMarkupTasklist} from './tasklist.js'; // code that runs for all markup content @@ -8,6 +9,7 @@ export function initMarkupContent() { renderMermaid(); renderMath(); renderCodeCopy(); + renderAsciinemaPlayer(); } // code that only runs for comments From aacb4cac77e60725d0f85b25a053a9bbc60424eb Mon Sep 17 00:00:00 2001 From: Jason Song Date: Tue, 17 Jan 2023 10:12:52 +0800 Subject: [PATCH 10/14] fix: typo --- web_src/less/index.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_src/less/index.less b/web_src/less/index.less index 3e80da180ce77..185bf7ca313b0 100644 --- a/web_src/less/index.less +++ b/web_src/less/index.less @@ -13,7 +13,7 @@ @import "./markup/content.less"; @import "./markup/codecopy.less"; @import "./code/linebutton.less"; -@import "./markup/asciicast"; +@import "./markup/asciicast.less"; @import "./chroma/base.less"; @import "./chroma/light.less"; From 4ecd7383880484d4cdc3357237ec62799ac01b7f Mon Sep 17 00:00:00 2001 From: Jason Song Date: Tue, 17 Jan 2023 18:15:29 +0800 Subject: [PATCH 11/14] chore: comments for poster --- web_src/js/markup/asciinema.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web_src/js/markup/asciinema.js b/web_src/js/markup/asciinema.js index 7404cabbfac1e..c1a775a1d494d 100644 --- a/web_src/js/markup/asciinema.js +++ b/web_src/js/markup/asciinema.js @@ -6,6 +6,8 @@ export async function renderAsciinemaPlayer() { 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', }); } From 22399ecdc81c77b3217f6335be186b7a7bcbdb0f Mon Sep 17 00:00:00 2001 From: Jason Song Date: Tue, 17 Jan 2023 20:04:51 +0800 Subject: [PATCH 12/14] Update web_src/js/markup/asciinema.js Co-authored-by: silverwind --- web_src/js/markup/asciinema.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_src/js/markup/asciinema.js b/web_src/js/markup/asciinema.js index c1a775a1d494d..d77c05b7aa5f3 100644 --- a/web_src/js/markup/asciinema.js +++ b/web_src/js/markup/asciinema.js @@ -2,7 +2,7 @@ export async function renderAsciinemaPlayer() { const els = document.querySelectorAll('.asciinema-player-container'); if (!els.length) return; - const player = await import(/* webpackChunkName: "asciinema" */'asciinema-player'); + const player = await import(/* webpackChunkName: "asciinema-player" */'asciinema-player'); for (const el of els) { player.create(el.getAttribute('data-asciinema-player-src'), el, { From 4869640442f6ddb36779742dc6d06e0a13e667b1 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Tue, 17 Jan 2023 20:36:31 +0800 Subject: [PATCH 13/14] chore: rename to asciicast.js --- web_src/js/markup/{asciinema.js => asciicast.js} | 0 web_src/js/markup/content.js | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename web_src/js/markup/{asciinema.js => asciicast.js} (100%) diff --git a/web_src/js/markup/asciinema.js b/web_src/js/markup/asciicast.js similarity index 100% rename from web_src/js/markup/asciinema.js rename to web_src/js/markup/asciicast.js diff --git a/web_src/js/markup/content.js b/web_src/js/markup/content.js index 005ffc577a4af..e4ec3d0b4baa6 100644 --- a/web_src/js/markup/content.js +++ b/web_src/js/markup/content.js @@ -1,7 +1,7 @@ import {renderMermaid} from './mermaid.js'; import {renderMath} from './math.js'; import {renderCodeCopy} from './codecopy.js'; -import {renderAsciinemaPlayer} from './asciinema.js'; +import {renderAsciinemaPlayer} from './asciicast.js'; import {initMarkupTasklist} from './tasklist.js'; // code that runs for all markup content From b0a17f652b9f5dc2c6b401a200f79695350be46c Mon Sep 17 00:00:00 2001 From: Jason Song Date: Tue, 17 Jan 2023 21:07:13 +0800 Subject: [PATCH 14/14] chore: reinstall asciinema-player --- package-lock.json | 20 +++++--------------- package.json | 2 +- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5cbe8ece85bfd..af317e1721cde 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", @@ -54,7 +55,6 @@ "@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", @@ -202,7 +202,6 @@ "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", - "dev": true, "dependencies": { "regenerator-runtime": "^0.13.11" }, @@ -2111,7 +2110,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/asciinema-player/-/asciinema-player-3.0.1.tgz", "integrity": "sha512-plm/C/MhOtZWysrfcT/rzxOuu8vxvvDSvF50pqZS6KpJUDmATedAhO54zktbE/g7RiaaYfzgX8xjRhlQdgISwA==", - "dev": true, "dependencies": { "@babel/runtime": "^7.15.4", "solid-js": "^1.3.0" @@ -7780,8 +7778,7 @@ "node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "node_modules/regexp-tree": { "version": "0.1.24", @@ -8282,7 +8279,6 @@ "version": "1.6.9", "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.6.9.tgz", "integrity": "sha512-kV3fMmm+1C2J95c8eDOPKGfZHnuAkHUBLG4hX1Xu08bXeAIPqmxuz/QdH3B8SIdTp3EatBVIyA6RCes3hrGzpg==", - "dev": true, "dependencies": { "csstype": "^3.1.0" } @@ -8290,8 +8286,7 @@ "node_modules/solid-js/node_modules/csstype": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", - "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==", - "dev": true + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" }, "node_modules/sortablejs": { "version": "1.15.0", @@ -10207,7 +10202,6 @@ "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", - "dev": true, "requires": { "regenerator-runtime": "^0.13.11" } @@ -11582,7 +11576,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/asciinema-player/-/asciinema-player-3.0.1.tgz", "integrity": "sha512-plm/C/MhOtZWysrfcT/rzxOuu8vxvvDSvF50pqZS6KpJUDmATedAhO54zktbE/g7RiaaYfzgX8xjRhlQdgISwA==", - "dev": true, "requires": { "@babel/runtime": "^7.15.4", "solid-js": "^1.3.0" @@ -15672,8 +15665,7 @@ "regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "regexp-tree": { "version": "0.1.24", @@ -16033,7 +16025,6 @@ "version": "1.6.9", "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.6.9.tgz", "integrity": "sha512-kV3fMmm+1C2J95c8eDOPKGfZHnuAkHUBLG4hX1Xu08bXeAIPqmxuz/QdH3B8SIdTp3EatBVIyA6RCes3hrGzpg==", - "dev": true, "requires": { "csstype": "^3.1.0" }, @@ -16041,8 +16032,7 @@ "csstype": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", - "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==", - "dev": true + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" } } }, diff --git a/package.json b/package.json index b820bcb505995..1ad52f9cd39ae 100644 --- a/package.json +++ b/package.json @@ -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", @@ -54,7 +55,6 @@ "@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",