Merge branch 'jackyzha0:v4' into v4

This commit is contained in:
enneaa 2025-03-31 10:05:15 +08:00 committed by GitHub
commit 48ec68a25c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 3248 additions and 44 deletions

View File

@ -1,5 +1,4 @@
import { JSX } from "preact"
import { randomIdNonSecure } from "../util/random"
const OverflowList = ({
children,
@ -13,8 +12,9 @@ const OverflowList = ({
)
}
let numExplorers = 0
export default () => {
const id = randomIdNonSecure()
const id = `list-${numExplorers++}`
return {
OverflowList: (props: JSX.HTMLAttributes<HTMLUListElement>) => (

View File

@ -53,17 +53,15 @@ export default ((opts?: Partial<Options>) => {
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
<div class={fileData.collapseToc ? "collapsed toc-content" : "toc-content"}>
<OverflowList>
{fileData.toc.map((tocEntry) => (
<li key={tocEntry.slug} class={`depth-${tocEntry.depth}`}>
<a href={`#${tocEntry.slug}`} data-for={tocEntry.slug}>
{tocEntry.text}
</a>
</li>
))}
</OverflowList>
</div>
<OverflowList class={fileData.collapseToc ? "collapsed toc-content" : "toc-content"}>
{fileData.toc.map((tocEntry) => (
<li key={tocEntry.slug} class={`depth-${tocEntry.depth}`}>
<a href={`#${tocEntry.slug}`} data-for={tocEntry.slug}>
{tocEntry.text}
</a>
</li>
))}
</OverflowList>
</div>
)
}

View File

@ -1,13 +1,13 @@
const observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
const slug = entry.target.id
const tocEntryElement = document.querySelector(`a[data-for="${slug}"]`)
const tocEntryElements = document.querySelectorAll(`a[data-for="${slug}"]`)
const windowHeight = entry.rootBounds?.height
if (windowHeight && tocEntryElement) {
if (windowHeight && tocEntryElements.length > 0) {
if (entry.boundingClientRect.y < windowHeight) {
tocEntryElement.classList.add("in-view")
tocEntryElements.forEach((tocEntryElement) => tocEntryElement.classList.add("in-view"))
} else {
tocEntryElement.classList.remove("in-view")
tocEntryElements.forEach((tocEntryElement) => tocEntryElement.classList.remove("in-view"))
}
}
}

View File

@ -5,7 +5,7 @@
flex-direction: column;
overflow-y: hidden;
min-height: 4rem;
min-height: 1.2rem;
flex: 0 1 auto;
&:has(button.toc-header.collapsed) {
flex: 0 1 1.2rem;
@ -45,23 +45,21 @@ button.toc-header {
}
}
.toc-content {
ul.toc-content {
list-style: none;
position: relative;
margin: 0.5rem 0;
padding: 0;
& ul {
list-style: none;
margin: 0.5rem 0;
padding: 0;
& > li > a {
color: var(--dark);
opacity: 0.35;
transition:
0.5s ease opacity,
0.3s ease color;
&.in-view {
opacity: 0.75;
}
list-style: none;
& > li > a {
color: var(--dark);
opacity: 0.35;
transition:
0.5s ease opacity,
0.3s ease color;
&.in-view {
opacity: 0.75;
}
}

View File

@ -55,8 +55,9 @@ async function generateSocialImage(
fonts,
loadAdditionalAsset: async (languageCode: string, segment: string) => {
if (languageCode === "emoji") {
return `data:image/svg+xml;base64,${btoa(await loadEmoji(getIconCode(segment)))}`
return await loadEmoji(getIconCode(segment))
}
return languageCode
},
})

View File

@ -65,6 +65,14 @@ ul,
}
}
article > mjx-container.MathJax {
display: flex;
> svg {
margin-left: auto;
margin-right: auto;
}
}
strong {
font-weight: $semiBoldWeight;
}
@ -546,8 +554,8 @@ video {
}
div:has(> .overflow) {
display: flex;
max-height: 100%;
overflow-y: hidden;
}
ul.overflow,

View File

@ -25,14 +25,23 @@ function toCodePoint(unicodeSurrogates: string) {
return r.join("-")
}
const twemoji = (code: string) =>
`https://cdnjs.cloudflare.com/ajax/libs/twemoji/15.1.0/svg/${code.toLowerCase()}.svg`
const emojiCache: Record<string, Promise<any>> = {}
export function loadEmoji(code: string) {
const type = "twemoji"
const key = type + ":" + code
if (key in emojiCache) return emojiCache[key]
return (emojiCache[key] = fetch(twemoji(code)).then((r) => r.text()))
type EmojiMap = {
codePointToName: Record<string, string>
nameToBase64: Record<string, string>
}
let emojimap: EmojiMap | undefined = undefined
export async function loadEmoji(code: string) {
if (!emojimap) {
const data = await import("./emojimap.json")
emojimap = data
}
const name = emojimap.codePointToName[`U+${code.toUpperCase()}`]
if (!name) throw new Error(`codepoint ${code} not found in map`)
const b64 = emojimap.nameToBase64[name]
if (!b64) throw new Error(`name ${name} not found in map`)
return b64
}

3190
quartz/util/emojimap.json Normal file

File diff suppressed because it is too large Load Diff