Refactor timestamps JS

It is safe to use innerHTML since the strings we are using it with are
under out control
This commit is contained in:
Kovid Goyal 2023-05-31 20:53:03 +05:30
parent d919864936
commit 2b3865f74e
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
3 changed files with 60 additions and 175 deletions

View file

@ -1,48 +1,44 @@
// 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'
/*jshint esversion: 11 */
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() {
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)
var loc = document.getElementById('timestamps-for-intro-video');
if (loc) {
const timestamps_element = get_timestamps_container(timestamps);
timestamps_element.addEventListener('click', handle_timestamp_click);
loc.appendChild(timestamps_element);
}
}
function handle_timestamp_click(e) {
if (e.target.tagName === 'TIME') {
const timestamp = e.target.getAttribute('datetime')
if (e.target.tagName.toUpperCase() === '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()
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 timestamps_container = document.createElement('section');
const rows_array = file.map(entry => {
const [row_element, timestamp_element, description_element]
= get_timestamp_elements(entry)
const [row_element, timestamp_element, description_element] = get_timestamp_elements(entry);
row_element.append(timestamp_element, description_element)
row_element.append(timestamp_element, description_element);
return row_element
})
rows_array.forEach(row => timestamps_container.appendChild(row))
return row_element;
});
rows_array.forEach(row => timestamps_container.appendChild(row));
timestamps_container.id = 'timestamps'
return timestamps_container
timestamps_container.id = 'timestamps';
return timestamps_container;
}
function get_timestamp_elements(entry) {
@ -50,148 +46,30 @@ function get_timestamp_elements(entry) {
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)
const new_element = document.createElement(element);
if (element === 'time') {
new_element.dateTime = new_element.textContent = text_content
return new_element
new_element.dateTime = new_element.textContent = text_content;
return new_element;
}
if (element === 'kbd' && !text_content) {
return
return;
}
if (text_content) {
new_element.textContent = text_content
new_element.textContent = text_content;
}
if (class_name) new_element.className = class_name
return new_element
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
const description_element = get_simple_element('p');
description_element.innerHTML = description;
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
window.addEventListener('load', init_timestamps);
})();

View file

@ -1,3 +1,4 @@
/*jshint esversion: 11 */
export default [
{
time: "00:00",
@ -5,7 +6,7 @@ export default [
},
{
time: "00:39",
description: "Pager: View command output in same window: Ctrl+Shift+g"
description: "Pager: View command output in same window: <kbd>Ctrl+Shift+g</kbd>"
},
{
time: "01:43",
@ -21,15 +22,15 @@ export default [
},
{
time: "03:03",
description: "Open files from ls output with mouse: Ctrl+Shift+Left-click"
description: "Open files from ls output with mouse: <kbd>Ctrl+Shift+Right-click</kbd>"
},
{
time: "04:04",
description: "Open files from ls output with keyboard: <Ctrl+Shift+P>y"
description: "Open files from ls output with keyboard: <kbd>Ctrl+Shift+P>y</kbd>"
},
{
time: "04:26",
description: "Open files on click: ls --hyperlink=auto"
description: "Open files on click: <code>ls --hyperlink=auto</code>"
},
{
time: "05:03",
@ -37,7 +38,7 @@ export default [
},
{
time: "05:45",
description: "Hyperlinked-grep kitten: Open grep output in editor"
description: "hyperlinked-grep kitten: Open grep output in editor"
},
{
time: "07:18",
@ -49,11 +50,11 @@ export default [
},
{
time: "10:01",
description: "Icat kitten: View images directly"
description: "icat kitten: View images directly"
},
{
time: "10:36",
description: "Icat kitten: Download & display image/gif from internet"
description: "icat kitten: Download & display image/gif from internet"
},
{
time: "11:03",
@ -61,11 +62,11 @@ export default [
},
{
time: "11:25",
description: "Icat kitten: Display image from remote server"
description: "icat kitten: Display image from remote server"
},
{
time: "12:04",
description: "Unicode-input kitten: Emojis in terminal "
description: "unicode-input kitten: Emojis in terminal "
},
{
time: "12:54",
@ -73,11 +74,11 @@ export default [
},
{
time: "13:36",
description: "Windows: Switch focus: Ctrl+Shift+<win_nr>"
description: "Windows: Switch focus: <kbd>Ctrl+Shift+&lt;win_nr&gt;</kbd>"
},
{
time: "13:48",
description: "Windows: Visual selection: Ctrl+Shift+F7"
description: "Windows: Visual selection: <kbd>Ctrl+Shift+F7</kbd>"
},
{
time: "13:58",
@ -85,11 +86,11 @@ export default [
},
{
time: "14:15",
description: "Interactive Kitty Shell: Ctrl+Shift+Esc"
description: "Interactive Kitty Shell: <kbd>Ctrl+Shift+Esc</kbd>"
},
{
time: "14:36",
description: "Broadcast text: launch --allow-remote-control kitty +kitten broadcast"
description: "Broadcast text: <code>launch --allow-remote-control kitty +kitten broadcast</code>"
},
{
time: "15:18",
@ -101,10 +102,10 @@ export default [
},
{
time: "16:34",
description: "Choose theme interactively: kitty +kitten themes -h"
description: "Choose theme interactively: <code>kitty +kitten themes -h</code>"
},
{
time: "17:23",
description: "Choose theme by name: kitty +kitten themes [options] [theme_name]"
description: "Choose theme by name: <code>kitty +kitten themes [options] [theme_name]</code>"
}
]
];

View file

@ -72,3 +72,9 @@ kitty
To get started see :doc:`quickstart`.
.. only:: dirhtml
.. raw:: html
<div id="timestamps-for-intro-video"></div>