mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-05-13 16:37:27 +00:00
Add timestamps under introductory video
This commit is contained in:
parent
2070dbb1e4
commit
329e7039da
4 changed files with 408 additions and 2 deletions
99
docs/_static/timestamps.css
vendored
Normal file
99
docs/_static/timestamps.css
vendored
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
:root {
|
||||
--border-radius: 5.5px;
|
||||
}
|
||||
|
||||
body[data-theme="dark"] {
|
||||
--kbd-bg: #ed9d13;
|
||||
--code-bg: #3c3c3c;
|
||||
--code-fg: var(--kbd-bg);
|
||||
--span-fg: #a6aaa7;
|
||||
}
|
||||
|
||||
body[data-theme="light"] {
|
||||
--kbd-bg: #ed9d13;
|
||||
--code-bg: #3c3c3c;
|
||||
--code-fg: #ffffff;
|
||||
--code-bg: #888888;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#timestamps {
|
||||
font-family: inherit;
|
||||
width: 100%;
|
||||
display: grid;
|
||||
max-width: 900px;
|
||||
grid-auto-rows: 2rem;
|
||||
line-height: 1.2;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
#timestamps .row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem .5rem;
|
||||
}
|
||||
|
||||
#timestamps time:hover {
|
||||
text-decoration: underline;
|
||||
padding-bottom: .2rem;
|
||||
}
|
||||
#timestamps time {
|
||||
color: var(--color-link);
|
||||
}
|
||||
#timestamps time:hover {
|
||||
cursor:pointer;
|
||||
}
|
||||
#timestamps time:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
#timestamps span {
|
||||
margin: 0;
|
||||
}
|
||||
#timestamps p {
|
||||
margin: 0.5rem;
|
||||
line-height: 1.2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
#timestamps kbd {
|
||||
border-radius: var(--border-radius);
|
||||
padding: .2rem;
|
||||
padding-top: 0.4rem;
|
||||
background: var(--kbd-bg);
|
||||
color: black;
|
||||
font-size: 0.9rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
@-moz-document url-prefix() {
|
||||
#timestamps kbd {
|
||||
padding: 0.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
#timestamps span {
|
||||
color: var(--tabs--label-text);
|
||||
}
|
||||
#timestamps strong {
|
||||
font-weight: normal;
|
||||
min-width: max-content;
|
||||
}
|
||||
#timestamps code {
|
||||
background: var(--code-bg);
|
||||
color: var(--code-fg);
|
||||
padding: 0.2rem 0.3rem;
|
||||
margin-left: .2rem;
|
||||
border-radius: var(--border-radius);
|
||||
min-width: max-content;
|
||||
font-size: 0.9rem;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding-top: 0.4rem;
|
||||
|
||||
}
|
||||
197
docs/_static/timestamps.js
vendored
Normal file
197
docs/_static/timestamps.js
vendored
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
// NOTE: After updating timestamps_source.js, please update the term in the ARRAY object as well,
|
||||
// so it can have the right styling
|
||||
import timestamps from './timestamps_source.js'
|
||||
|
||||
const ARRAY = {
|
||||
SPAN: null,
|
||||
KBD: ['Ctrl+Shift+g', "Ctrl+Shift+Left-click", '<Ctrl+Shift+P>y', 'Ctrl+Shift+F7', 'Ctrl+Shift+<num>', 'Ctrl+Shift+Esc', 'Ctrl+Shift+<win_nr>'],
|
||||
CODE: ['ls --hyperlink=auto', 'launch --allow-remote-control kitty +kitten broadcast', 'kitty +kitten themes -h', 'kitty +kitten themes [options] [theme_name]']
|
||||
}
|
||||
|
||||
function init_timestamps() {
|
||||
const timestamps_element = get_timestamps_container(timestamps)
|
||||
timestamps_element.addEventListener('click', handle_timestamp_click)
|
||||
|
||||
document.querySelector('.caption-text').insertAdjacentElement('afterend', timestamps_element)
|
||||
}
|
||||
|
||||
function handle_timestamp_click(e) {
|
||||
if (e.target.tagName === 'TIME') {
|
||||
const timestamp = e.target.getAttribute('datetime')
|
||||
if (timestamp) {
|
||||
const [minutes, seconds] = timestamp.split(':')
|
||||
const totalSeconds = parseInt(minutes) * 60 + parseInt(seconds)
|
||||
const video = document.querySelector('video')
|
||||
video.currentTime = totalSeconds
|
||||
video.play()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function get_timestamps_container(file) {
|
||||
const timestamps_container = document.createElement('section')
|
||||
|
||||
const rows_array = file.map(entry => {
|
||||
const [row_element, timestamp_element, description_element]
|
||||
= get_timestamp_elements(entry)
|
||||
|
||||
row_element.append(timestamp_element, description_element)
|
||||
|
||||
return row_element
|
||||
})
|
||||
rows_array.forEach(row => timestamps_container.appendChild(row))
|
||||
|
||||
timestamps_container.id = 'timestamps'
|
||||
return timestamps_container
|
||||
}
|
||||
|
||||
function get_timestamp_elements(entry) {
|
||||
return [
|
||||
get_simple_element('div', null, 'row'),
|
||||
get_simple_element('time', entry.time),
|
||||
get_updated_description_element(entry.description)
|
||||
]
|
||||
}
|
||||
|
||||
function get_simple_element(element, text_content = null, class_name = null) {
|
||||
const new_element = document.createElement(element)
|
||||
if (element === 'time') {
|
||||
new_element.dateTime = new_element.textContent = text_content
|
||||
return new_element
|
||||
}
|
||||
if (element === 'kbd' && !text_content) {
|
||||
return
|
||||
}
|
||||
if (text_content) {
|
||||
new_element.textContent = text_content
|
||||
}
|
||||
if (class_name) new_element.className = class_name
|
||||
return new_element
|
||||
}
|
||||
|
||||
function get_updated_description_element(description) {
|
||||
const span_content_array = []
|
||||
|
||||
const strong = get_strong_object(span_content_array, description)
|
||||
const kbd = get_kbd_object(span_content_array, description)
|
||||
const code = get_code_object(span_content_array, description)
|
||||
const span_element = get_span_element(span_content_array, description)
|
||||
|
||||
const array_of_elements = [strong.element, span_element, kbd.element, code.element].filter(Boolean)
|
||||
|
||||
const description_element = get_simple_element('p')
|
||||
description_element.append(...array_of_elements)
|
||||
|
||||
return description_element
|
||||
}
|
||||
|
||||
function get_strong_object(span_content_array, description) {
|
||||
const strong = {
|
||||
element: null,
|
||||
updated_description: null
|
||||
}
|
||||
set_strong_values(description, strong)
|
||||
|
||||
if (strong.element) {
|
||||
span_content_array.push(strong.updated_description)
|
||||
}
|
||||
return strong
|
||||
}
|
||||
|
||||
function set_strong_values(description, strong) {
|
||||
const matches = description.match(/^[^:]+/)
|
||||
strong.element = get_simple_element('strong', matches)
|
||||
strong.updated_description = delete_keywords_from_description(matches, description)
|
||||
}
|
||||
|
||||
function get_kbd_object(span_content_array, description) {
|
||||
const kbd = {
|
||||
element: null,
|
||||
updated_description: null
|
||||
}
|
||||
|
||||
set_kbd_values(span_content_array, description, kbd)
|
||||
|
||||
if (kbd.updated_description) {
|
||||
span_content_array[0] = kbd.updated_description
|
||||
}
|
||||
|
||||
return kbd
|
||||
}
|
||||
|
||||
function set_kbd_values(span_content_array, description, kbd) {
|
||||
const last_updated_description = span_content_array.length > 0 ? span_content_array[0] : description
|
||||
|
||||
const matching_words = get_matched_keyword(ARRAY.KBD, last_updated_description);
|
||||
const has_matches = matching_words?.length > 0
|
||||
|
||||
if (!has_matches) return
|
||||
|
||||
kbd.element = get_simple_element('kbd', matching_words)
|
||||
kbd.updated_description =
|
||||
delete_keywords_from_description(
|
||||
matching_words,
|
||||
last_updated_description
|
||||
)
|
||||
}
|
||||
|
||||
function get_span_element(span_content_array, description) {
|
||||
let span_text_content = span_content_array.length < 1 ? description : span_content_array[0]
|
||||
span_content_array.push(span_text_content)
|
||||
|
||||
return get_simple_element('span', span_text_content)
|
||||
}
|
||||
|
||||
function get_code_object(span_content_array, description) {
|
||||
const code = {
|
||||
element: null,
|
||||
updated_description: null
|
||||
}
|
||||
set_code_values(span_content_array, description, code)
|
||||
|
||||
if (code.updated_description) {
|
||||
span_content_array[0] = code.updated_description
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
function set_code_values(span_content_array, description, code) {
|
||||
const last_updated_description = span_content_array.length > 0 ? span_content_array[0] : description
|
||||
|
||||
const matching_words = get_matched_keyword(ARRAY.CODE, last_updated_description);
|
||||
|
||||
const has_matches = matching_words?.length > 0
|
||||
|
||||
if (!has_matches) return
|
||||
|
||||
code.element = get_simple_element('code', matching_words)
|
||||
code.updated_description =
|
||||
delete_keywords_from_description(
|
||||
matching_words,
|
||||
last_updated_description
|
||||
)
|
||||
}
|
||||
|
||||
function get_matched_keyword(substrings, updated_description) {
|
||||
if (typeof updated_description !== 'string') return null
|
||||
|
||||
const matches = substrings.filter(substring => {
|
||||
return updated_description.includes(substring)
|
||||
})
|
||||
if (matches.length < 1) return
|
||||
|
||||
return matches
|
||||
}
|
||||
|
||||
function delete_keywords_from_description(matches, description) {
|
||||
if (typeof matches === 'string') {
|
||||
return description.replace(matches, '')
|
||||
}
|
||||
const combined_regex = new RegExp(matches.map(escape_regex).join('|'), 'g')
|
||||
return description.replace(combined_regex, '')
|
||||
}
|
||||
|
||||
function escape_regex(string) {
|
||||
return string.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
||||
}
|
||||
window.onload = init_timestamps
|
||||
110
docs/_static/timestamps_source.js
vendored
Normal file
110
docs/_static/timestamps_source.js
vendored
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
export default [
|
||||
{
|
||||
time: "00:00",
|
||||
description: "Intro"
|
||||
},
|
||||
{
|
||||
time: "00:39",
|
||||
description: "Pager: View command output in same window: Ctrl+Shift+g"
|
||||
},
|
||||
{
|
||||
time: "01:43",
|
||||
description: "Pager: View command output in a separate window"
|
||||
},
|
||||
{
|
||||
time: "02:14",
|
||||
description: "Pager: Uses shell integration in kitty"
|
||||
},
|
||||
{
|
||||
time: "02:27",
|
||||
description: "Tab text: The output of cwd and last cmd "
|
||||
},
|
||||
{
|
||||
time: "03:03",
|
||||
description: "Open files from ls output with mouse: Ctrl+Shift+Left-click"
|
||||
},
|
||||
{
|
||||
time: "04:04",
|
||||
description: "Open files from ls output with keyboard: <Ctrl+Shift+P>y"
|
||||
},
|
||||
{
|
||||
time: "04:26",
|
||||
description: "Open files on click: ls --hyperlink=auto"
|
||||
},
|
||||
{
|
||||
time: "05:03",
|
||||
description: "Open files on click: Filetype settings in open-actions.conf"
|
||||
},
|
||||
{
|
||||
time: "05:45",
|
||||
description: "Hyperlinked-grep kitten: Open grep output in editor"
|
||||
},
|
||||
{
|
||||
time: "07:18",
|
||||
description: "Remote-file kitten: View remote files locally"
|
||||
},
|
||||
{
|
||||
time: "08:31",
|
||||
description: "Remote-file kitten: Edit remote files locally"
|
||||
},
|
||||
{
|
||||
time: "10:01",
|
||||
description: "Icat kitten: View images directly"
|
||||
},
|
||||
{
|
||||
time: "10:36",
|
||||
description: "Icat kitten: Download & display image/gif from internet"
|
||||
},
|
||||
{
|
||||
time: "11:03",
|
||||
description: "Kitty Graphics Protocol: Live image preview in ranger"
|
||||
},
|
||||
{
|
||||
time: "11:25",
|
||||
description: "Icat kitten: Display image from remote server"
|
||||
},
|
||||
{
|
||||
time: "12:04",
|
||||
description: "Unicode-input kitten: Emojis in terminal "
|
||||
},
|
||||
{
|
||||
time: "12:54",
|
||||
description: "Windows: Intro"
|
||||
},
|
||||
{
|
||||
time: "13:36",
|
||||
description: "Windows: Switch focus: Ctrl+Shift+<win_nr>"
|
||||
},
|
||||
{
|
||||
time: "13:48",
|
||||
description: "Windows: Visual selection: Ctrl+Shift+F7"
|
||||
},
|
||||
{
|
||||
time: "13:58",
|
||||
description: "Windows: Simultaneous input"
|
||||
},
|
||||
{
|
||||
time: "14:15",
|
||||
description: "Interactive Kitty Shell: Ctrl+Shift+Esc"
|
||||
},
|
||||
{
|
||||
time: "14:36",
|
||||
description: "Broadcast text: launch --allow-remote-control kitty +kitten broadcast"
|
||||
},
|
||||
{
|
||||
time: "15:18",
|
||||
description: "Kitty Remote Control Protocol"
|
||||
},
|
||||
{
|
||||
time: "15:52",
|
||||
description: "Interactive Kitty Shell: Help"
|
||||
},
|
||||
{
|
||||
time: "16:34",
|
||||
description: "Choose theme interactively: kitty +kitten themes -h"
|
||||
},
|
||||
{
|
||||
time: "17:23",
|
||||
description: "Choose theme by name: kitty +kitten themes [options] [theme_name]"
|
||||
}
|
||||
]
|
||||
|
|
@ -156,8 +156,8 @@ html_theme_options: Dict[str, Any] = {
|
|||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
html_favicon = html_logo = '../logo/kitty.svg'
|
||||
html_css_files = ['custom.css']
|
||||
html_js_files = ['custom.js']
|
||||
html_css_files = ['custom.css', 'style.css']
|
||||
html_js_files = ['custom.js', ('timestamps.js', {'type': 'module'})]
|
||||
|
||||
# Custom sidebar templates, must be a dictionary that maps document names
|
||||
# to template names.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue