Skip to content

Commit 89d6356

Browse files
authored
Use monospace font for timecodes, don't use list icons, fix expando row positioning (#356)
* Use monospace font for timecodes, don't use list icons, fix expando row positioning * Remove `00:` hour prefix from every timecode * Fix /transcripts rendering
1 parent ef63c19 commit 89d6356

37 files changed

+6569
-6478
lines changed

src/components/Layout/MarkdownStyles.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,16 @@ export const MarkdownStyles = createGlobalStyle`
3737
word-break: break-word;
3838
word-wrap: break-word;
3939
}
40+
ul {
41+
list-style: none;
42+
}
4043
li > details {
4144
display: block;
4245
}
4346
summary {
4447
cursor: pointer;
48+
margin-left: -2rem;
4549
user-select: none;
46-
list-style: none;
4750
display: block;
4851
&::marker,
4952
&::-webkit-details-marker {

src/helpers/rehypeWrapTimecodes.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { visit } from "unist-util-visit";
2+
import type { Root, Element, Text, ElementContent } from "hast";
3+
4+
/**
5+
* Rehype plugin that wraps timecode patterns in <code> tags.
6+
* Looks for list items that start with `[<timecode link>]` pattern
7+
* and wraps them in <code> tags for styling.
8+
*
9+
* Input: <li>[<a href="#intro">00:00</a>] Intro</li>
10+
* Output: <li><code>[<a href="#intro">00:00</a>]</code> Intro</li>
11+
*/
12+
export default function rehypeWrapTimecodes() {
13+
return (tree: Root) => {
14+
visit(tree, "element", (node) => {
15+
// Only process <li> elements
16+
if (node.tagName !== "li") {
17+
return;
18+
}
19+
20+
// Check if first child is a text node starting with "["
21+
if (node.children.length < 3) {
22+
return;
23+
}
24+
25+
const firstChild = node.children[0];
26+
if (firstChild.type !== "text" || !firstChild.value.startsWith("[")) {
27+
return;
28+
}
29+
30+
// Check if second child is a link with a timecode pattern
31+
const secondChild = node.children[1];
32+
if (secondChild.type !== "element" || secondChild.tagName !== "a") {
33+
return;
34+
}
35+
36+
// Check if the link text matches timecode pattern (HH:MM:SS or MM:SS)
37+
const linkText =
38+
secondChild.children[0]?.type === "text"
39+
? secondChild.children[0].value
40+
: "";
41+
const timecodePattern = /^\d{1,2}:\d{2}(:\d{2})?$/;
42+
if (!timecodePattern.test(linkText)) {
43+
return;
44+
}
45+
46+
// Check if third child is a text node starting with "]"
47+
const thirdChild = node.children[2];
48+
if (thirdChild.type !== "text" || !thirdChild.value.startsWith("]")) {
49+
return;
50+
}
51+
52+
// Extract and modify the bracket text nodes
53+
const openingBracket: Text = {
54+
type: "text",
55+
value: "[",
56+
};
57+
58+
const closingBracket: Text = {
59+
type: "text",
60+
value: "]",
61+
};
62+
63+
// Update the original text nodes to remove the brackets
64+
const firstTextNode = firstChild as Text;
65+
firstTextNode.value = firstTextNode.value.slice(1); // Remove leading "["
66+
67+
const thirdTextNode = thirdChild as Text;
68+
thirdTextNode.value = thirdTextNode.value.slice(1); // Remove leading "]"
69+
70+
// Create the <code> wrapper with the timecode content
71+
const codeElement: Element = {
72+
type: "element",
73+
tagName: "code",
74+
properties: {},
75+
children: [openingBracket, secondChild, closingBracket],
76+
};
77+
78+
// Rebuild the children array
79+
const remainingContent = node.children.slice(2);
80+
node.children = [codeElement, ...remainingContent];
81+
});
82+
};
83+
}

src/helpers/retrieveMdPages.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import rehypeSlug from "rehype-slug";
1111
import remarkHeadings, { hasHeadingsData } from "@vcarl/remark-headings";
1212
import { toString } from "mdast-util-to-string";
1313
import rehypeWrapFirstList from "./rehypeWrapFirstList";
14+
import rehypeWrapTimecodes from "./rehypeWrapTimecodes";
1415

1516
const loadMd = async (path: string) => {
1617
const fullPath = join(process.cwd(), `${path}.md`);
@@ -55,6 +56,7 @@ export const processMd = (mdSource: string, options?: ProcessMdOptions) => {
5556
.use(remarkHeadings as ReturnType<ReturnType<typeof unified>["use"]>)
5657
.use(remarkRehype, { allowDangerousHtml: true })
5758
.use(rehypeSlug)
59+
.use(rehypeWrapTimecodes)
5860
.use(rehypeWrapFirstList)
5961
.use(rehypeStringify, { allowDangerousHtml: true });
6062
}

src/pages/transcripts.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ export default function Transcripts({
3838
<p>
3939
<em>Transcript from {date}</em>
4040
</p>
41-
<div dangerouslySetInnerHTML={{ __html: latest.html }} />
41+
<div
42+
className="markdown"
43+
dangerouslySetInnerHTML={{ __html: latest.html }}
44+
/>
4245
</div>
4346
</>
4447
)}
@@ -68,7 +71,7 @@ export async function getStaticProps() {
6871
title: latest.title,
6972
description: latest.description,
7073
date: latest.date,
71-
html: processMd(latest.content).html,
74+
html: processMd(latest.content, { wrapFirstList: true }).html,
7275
},
7376
},
7477
};

src/transcripts/ankita-kulkarni.md

Lines changed: 187 additions & 187 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)