mirror of
https://github.com/jackyzha0/quartz.git
synced 2025-12-20 11:24:05 -06:00
Merge branch 'jackyzha0:v4' into v4
This commit is contained in:
commit
48ec68a25c
@ -1,5 +1,4 @@
|
|||||||
import { JSX } from "preact"
|
import { JSX } from "preact"
|
||||||
import { randomIdNonSecure } from "../util/random"
|
|
||||||
|
|
||||||
const OverflowList = ({
|
const OverflowList = ({
|
||||||
children,
|
children,
|
||||||
@ -13,8 +12,9 @@ const OverflowList = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let numExplorers = 0
|
||||||
export default () => {
|
export default () => {
|
||||||
const id = randomIdNonSecure()
|
const id = `list-${numExplorers++}`
|
||||||
|
|
||||||
return {
|
return {
|
||||||
OverflowList: (props: JSX.HTMLAttributes<HTMLUListElement>) => (
|
OverflowList: (props: JSX.HTMLAttributes<HTMLUListElement>) => (
|
||||||
|
|||||||
@ -53,8 +53,7 @@ export default ((opts?: Partial<Options>) => {
|
|||||||
<polyline points="6 9 12 15 18 9"></polyline>
|
<polyline points="6 9 12 15 18 9"></polyline>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<div class={fileData.collapseToc ? "collapsed toc-content" : "toc-content"}>
|
<OverflowList class={fileData.collapseToc ? "collapsed toc-content" : "toc-content"}>
|
||||||
<OverflowList>
|
|
||||||
{fileData.toc.map((tocEntry) => (
|
{fileData.toc.map((tocEntry) => (
|
||||||
<li key={tocEntry.slug} class={`depth-${tocEntry.depth}`}>
|
<li key={tocEntry.slug} class={`depth-${tocEntry.depth}`}>
|
||||||
<a href={`#${tocEntry.slug}`} data-for={tocEntry.slug}>
|
<a href={`#${tocEntry.slug}`} data-for={tocEntry.slug}>
|
||||||
@ -64,7 +63,6 @@ export default ((opts?: Partial<Options>) => {
|
|||||||
))}
|
))}
|
||||||
</OverflowList>
|
</OverflowList>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
const observer = new IntersectionObserver((entries) => {
|
const observer = new IntersectionObserver((entries) => {
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
const slug = entry.target.id
|
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
|
const windowHeight = entry.rootBounds?.height
|
||||||
if (windowHeight && tocEntryElement) {
|
if (windowHeight && tocEntryElements.length > 0) {
|
||||||
if (entry.boundingClientRect.y < windowHeight) {
|
if (entry.boundingClientRect.y < windowHeight) {
|
||||||
tocEntryElement.classList.add("in-view")
|
tocEntryElements.forEach((tocEntryElement) => tocEntryElement.classList.add("in-view"))
|
||||||
} else {
|
} else {
|
||||||
tocEntryElement.classList.remove("in-view")
|
tocEntryElements.forEach((tocEntryElement) => tocEntryElement.classList.remove("in-view"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
min-height: 4rem;
|
min-height: 1.2rem;
|
||||||
flex: 0 1 auto;
|
flex: 0 1 auto;
|
||||||
&:has(button.toc-header.collapsed) {
|
&:has(button.toc-header.collapsed) {
|
||||||
flex: 0 1 1.2rem;
|
flex: 0 1 1.2rem;
|
||||||
@ -45,14 +45,13 @@ button.toc-header {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc-content {
|
ul.toc-content {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
& ul {
|
|
||||||
list-style: none;
|
|
||||||
margin: 0.5rem 0;
|
margin: 0.5rem 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
|
list-style: none;
|
||||||
& > li > a {
|
& > li > a {
|
||||||
color: var(--dark);
|
color: var(--dark);
|
||||||
opacity: 0.35;
|
opacity: 0.35;
|
||||||
@ -63,7 +62,6 @@ button.toc-header {
|
|||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@for $i from 0 through 6 {
|
@for $i from 0 through 6 {
|
||||||
& .depth-#{$i} {
|
& .depth-#{$i} {
|
||||||
|
|||||||
@ -55,8 +55,9 @@ async function generateSocialImage(
|
|||||||
fonts,
|
fonts,
|
||||||
loadAdditionalAsset: async (languageCode: string, segment: string) => {
|
loadAdditionalAsset: async (languageCode: string, segment: string) => {
|
||||||
if (languageCode === "emoji") {
|
if (languageCode === "emoji") {
|
||||||
return `data:image/svg+xml;base64,${btoa(await loadEmoji(getIconCode(segment)))}`
|
return await loadEmoji(getIconCode(segment))
|
||||||
}
|
}
|
||||||
|
|
||||||
return languageCode
|
return languageCode
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@ -65,6 +65,14 @@ ul,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
article > mjx-container.MathJax {
|
||||||
|
display: flex;
|
||||||
|
> svg {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
strong {
|
strong {
|
||||||
font-weight: $semiBoldWeight;
|
font-weight: $semiBoldWeight;
|
||||||
}
|
}
|
||||||
@ -546,8 +554,8 @@ video {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div:has(> .overflow) {
|
div:has(> .overflow) {
|
||||||
display: flex;
|
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul.overflow,
|
ul.overflow,
|
||||||
|
|||||||
@ -25,14 +25,23 @@ function toCodePoint(unicodeSurrogates: string) {
|
|||||||
return r.join("-")
|
return r.join("-")
|
||||||
}
|
}
|
||||||
|
|
||||||
const twemoji = (code: string) =>
|
type EmojiMap = {
|
||||||
`https://cdnjs.cloudflare.com/ajax/libs/twemoji/15.1.0/svg/${code.toLowerCase()}.svg`
|
codePointToName: Record<string, string>
|
||||||
const emojiCache: Record<string, Promise<any>> = {}
|
nameToBase64: Record<string, string>
|
||||||
|
}
|
||||||
export function loadEmoji(code: string) {
|
|
||||||
const type = "twemoji"
|
let emojimap: EmojiMap | undefined = undefined
|
||||||
const key = type + ":" + code
|
export async function loadEmoji(code: string) {
|
||||||
if (key in emojiCache) return emojiCache[key]
|
if (!emojimap) {
|
||||||
|
const data = await import("./emojimap.json")
|
||||||
return (emojiCache[key] = fetch(twemoji(code)).then((r) => r.text()))
|
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
3190
quartz/util/emojimap.json
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user