mirror of
https://github.com/jackyzha0/quartz.git
synced 2026-03-24 15:05:42 -05:00
Quartz sync: Jul 9, 2024, 6:42 PM
This commit is contained in:
parent
f1e1384a59
commit
4781d2afd0
@ -2,7 +2,7 @@
|
||||
title: 2024-07-06
|
||||
author: ["Justin"]
|
||||
date: 2024-07-06T06:20:00-04:00
|
||||
lastmod: 2024-07-06T19:04:54-04:00
|
||||
lastmod: 2024-07-08T09:04:26-04:00
|
||||
draft: false
|
||||
---
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
title: 2024-07-07
|
||||
author: ["Justin"]
|
||||
date: 2024-07-07T05:16:00-04:00
|
||||
lastmod: 2024-07-07T07:49:51-04:00
|
||||
lastmod: 2024-07-07T21:23:11-04:00
|
||||
draft: false
|
||||
---
|
||||
|
||||
@ -14,9 +14,10 @@ draft: false
|
||||
|
||||
### Tasks {#tasks}
|
||||
|
||||
- [ ] Chinese
|
||||
- [ ] Read
|
||||
- [ ] Anki stuff
|
||||
- [X] Chinese
|
||||
- 646!
|
||||
- [X] Read
|
||||
- [X] Anki stuff
|
||||
- [X] CSS spacing
|
||||
- Think I got it - distinct CSS for h\* + ul vs. p, cumbersome, but with
|
||||
variables shouldn't hurt too much to change down the line.
|
||||
|
||||
52
content/daily/2024/07/2024-07-08.md
Normal file
52
content/daily/2024/07/2024-07-08.md
Normal file
@ -0,0 +1,52 @@
|
||||
---
|
||||
title: 2024-07-08
|
||||
author: ["Justin"]
|
||||
date: 2024-07-08T06:23:00-04:00
|
||||
lastmod: 2024-07-08T22:24:59-04:00
|
||||
draft: false
|
||||
---
|
||||
|
||||
<div class="outline-1 jvc">
|
||||
|
||||
## Agenda {#agenda}
|
||||
|
||||
<div class="outline-2 jvc">
|
||||
|
||||
### Tasks {#tasks}
|
||||
|
||||
- [X] Chinese
|
||||
- 657!
|
||||
- [X] Read
|
||||
- [X] Build
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="outline-1 jvc">
|
||||
|
||||
## Notes {#notes}
|
||||
|
||||
<div class="outline-2 jvc">
|
||||
|
||||
### Reading {#reading}
|
||||
|
||||
- Reading [Hong, Ruixin and Zhang, Hongming and Pan, Xiaoman and Yu, Dong and
|
||||
Zhang, Changshui :: Abstraction-of-Thought Makes Language Models Better
|
||||
Reasoners]({{< relref "../../../references/hongAbstractionofThoughtMakesLanguage2024.md" >}})[^fn:1]
|
||||
- Need to come back to this, will finish tomorrow.
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="outline-1 jvc">
|
||||
|
||||
## Journal {#journal}
|
||||
|
||||
Weekend over. Womp. Want to mess around with some LLM stuff today. Got the
|
||||
reference section of the site up. Should put all books, etc. etc. stuff there.
|
||||
|
||||
</div>
|
||||
|
||||
[^fn:1]: Ruixin Hong et al., “Abstraction-of-Thought Makes Language Models Better Reasoners” (arXiv, June 2024).
|
||||
51
content/daily/2024/07/2024-07-09.md
Normal file
51
content/daily/2024/07/2024-07-09.md
Normal file
@ -0,0 +1,51 @@
|
||||
---
|
||||
title: 2024-07-09
|
||||
author: ["Justin"]
|
||||
date: 2024-07-09T07:07:00-04:00
|
||||
lastmod: 2024-07-09T15:32:37-04:00
|
||||
draft: false
|
||||
---
|
||||
|
||||
<div class="outline-1 jvc">
|
||||
|
||||
## Agenda {#agenda}
|
||||
|
||||
<div class="outline-2 jvc">
|
||||
|
||||
### Tasks {#tasks}
|
||||
|
||||
- [ ] Chinese
|
||||
- [ ] Read
|
||||
- [ ] Build
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="outline-1 jvc">
|
||||
|
||||
## Notes {#notes}
|
||||
|
||||
<div class="outline-2 jvc">
|
||||
|
||||
### Reading {#reading}
|
||||
|
||||
<div class="outline-3 jvc">
|
||||
|
||||
#### [Blow Out Kits – One Medic’s Perspective](https://civiliangunfighter.wordpress.com/2015/06/17/blow-out-kits-one-medics-perspective/) <span class="tag"><span class="medic">medic</span></span> {#blow-out-kits-one-medic-s-perspective}
|
||||
|
||||
- Just kind of wandered into this, I should take a first-aid class.
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="outline-1 jvc">
|
||||
|
||||
## Journal {#journal}
|
||||
|
||||
Slower day. Stuck doing non-computer stuff so a bit behind on things.
|
||||
|
||||
</div>
|
||||
@ -28,3 +28,5 @@ Before this I was planning on doing some mass exports with a doomscript but I fo
|
||||
Most of these will be just random things I'm reading, I think. I still need to figure out a good way to do a slip-box. I have a org server extension I can send links to but I forget to do it. Same with pocket (non-open source reasons aside, the emacs package works well)
|
||||
|
||||
- [Daily Notes](/daily/)
|
||||
- [Main](/main/)
|
||||
- [References](/references/)
|
||||
|
||||
146
content/references/hongAbstractionofThoughtMakesLanguage2024.md
Normal file
146
content/references/hongAbstractionofThoughtMakesLanguage2024.md
Normal file
@ -0,0 +1,146 @@
|
||||
---
|
||||
title: "Hong, Ruixin and Zhang, Hongming and Pan, Xiaoman and Yu, Dong and Zhang, Changshui :: Abstraction-of-Thought Makes Language Models Better Reasoners"
|
||||
author: ["Justin"]
|
||||
date: 2024-07-08T09:29:00-04:00
|
||||
lastmod: 2024-07-08T16:15:51-04:00
|
||||
tags: ["machine-learning", "prompting"]
|
||||
draft: false
|
||||
---
|
||||
|
||||
<div class="outline-1 jvc">
|
||||
|
||||
## Paper {#paper}
|
||||
|
||||
Abstraction-of-Thought (AoT) is a novel structured reasoning format designed to
|
||||
enhance language models' abstract reasoning capabilities. Unlike the
|
||||
step-by-step Chain-of-Thought (CoT) method, AoT requires models to consider
|
||||
problems at varying levels of abstraction before delving into concrete details.
|
||||
|
||||
</div>
|
||||
|
||||
<div class="outline-1 jvc">
|
||||
|
||||
## Implementation {#implementation}
|
||||
|
||||
These are various implementations I've created or wandered into.
|
||||
|
||||
<details>
|
||||
<summary>Python</summary>
|
||||
<div class="details">
|
||||
|
||||
The python one I created myself, was pondering using it for some of my projects.
|
||||
|
||||
```python
|
||||
|
||||
import openai
|
||||
|
||||
client = openai.OpenAI()
|
||||
|
||||
def abstraction_of_thought(problem):
|
||||
# Step 1: High-level planning
|
||||
high_level_prompt = f"""Problem: {problem}
|
||||
|
||||
Let's think logically and provide an abstract higher-order plan on how to
|
||||
solve this kind of problem. Don't dive into small details, only provide
|
||||
a high-level plan."""
|
||||
|
||||
high_level_response = client.chat.completions.create(
|
||||
model="gpt-3.5-turbo",
|
||||
messages=[{"role": "user", "content": high_level_prompt}]
|
||||
)
|
||||
high_level_plan = high_level_response.choices[0].message.content
|
||||
|
||||
# Step 2: Detailed planning
|
||||
detailed_prompt = f"""High-level plan: {high_level_plan}
|
||||
|
||||
Provide a more detailed plan. What specific steps should we take? On
|
||||
what details should we pay attention?"""
|
||||
|
||||
detailed_response = client.chat.completions.create(
|
||||
model="gpt-3.5-turbo",
|
||||
messages=[{"role": "user", "content": detailed_prompt}]
|
||||
)
|
||||
detailed_plan = detailed_response.choices[0].message.content
|
||||
|
||||
# Step 3: Problem-solving
|
||||
solve_prompt = f"""Problem: {problem}
|
||||
High-level plan: {high_level_plan}
|
||||
Detailed plan: {detailed_plan}
|
||||
|
||||
Now, apply this plan to solve the problem and provide the final solution."""
|
||||
|
||||
solve_response = client.chat.completions.create(
|
||||
model="gpt-3.5-turbo",
|
||||
messages=[{"role": "user", "content": solve_prompt}]
|
||||
)
|
||||
solution = solve_response.choices[0].message.content
|
||||
|
||||
# Step 4: Summarizing
|
||||
summary_prompt = f"""Solution: {solution}
|
||||
|
||||
Provide a short, concise final answer based on this solution."""
|
||||
|
||||
summary_response = client.chat.completions.create(
|
||||
model="gpt-3.5-turbo",
|
||||
messages=[{"role": "user", "content": summary_prompt}]
|
||||
)
|
||||
final_answer = summary_response.choices[0].message.content
|
||||
|
||||
return {
|
||||
"high_level_plan": high_level_plan,
|
||||
"detailed_plan": detailed_plan,
|
||||
"solution": solution,
|
||||
"final_answer": final_answer
|
||||
}
|
||||
|
||||
# Example usage
|
||||
problem = """I have an orange, five raspberries, two books,
|
||||
three plums, a pencil, and a grape. How many fruits do I have?"""
|
||||
result = abstraction_of_thought(problem)
|
||||
|
||||
print("High-level plan:", result["high_level_plan"])
|
||||
print("\nDetailed plan:", result["detailed_plan"])
|
||||
print("\nSolution:", result["solution"])
|
||||
print("\nFinal answer:", result["final_answer"])
|
||||
```
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Elisp</summary>
|
||||
<div class="details">
|
||||
|
||||
This elisp implementation is in the
|
||||
[GitHub - s-kostyaev/ellama](https://github.com/s-kostyaev/ellama) package.
|
||||
|
||||
```elisp
|
||||
This is an elisp implementation of abstraction of thought
|
||||
|
||||
(defun ellama-solve-reasoning-problem (problem)
|
||||
"Solve reasoning PROBLEM with absctraction of thought.
|
||||
Problem will be solved with the chain of questions to LLM."
|
||||
(interactive "sProblem: ")
|
||||
(ellama-chain
|
||||
problem
|
||||
'((:chat t
|
||||
:transform (lambda (problem _)
|
||||
(format "Problem:
|
||||
%s
|
||||
|
||||
Let's think logically and provide abstract higher order plan how to solve this
|
||||
kind of problems. Don't dive into small details only provide high-level plan."
|
||||
problem)))
|
||||
(:chat t
|
||||
:transform (lambda ( )
|
||||
"Provide more detailed plan. On what details should we pay attention?"))
|
||||
(:chat t
|
||||
:transform (lambda ( )
|
||||
"Now revise the plan and provide the final solution."))
|
||||
(:chat t
|
||||
:transform (lambda ( )
|
||||
"Provide short final answer based on final solution.")))))
|
||||
```
|
||||
</div>
|
||||
</details>
|
||||
|
||||
</div>
|
||||
36
functions.ts
36
functions.ts
@ -1,8 +1,32 @@
|
||||
import { Options } from "./quartz/components/ExplorerNode"
|
||||
|
||||
const toTitleCase = (str: string): string => {
|
||||
return str.replace(/\w\S*/g, (txt: string): string => {
|
||||
return txt.charAt(0).toUpperCase() + txt.slice(1).toLowerCase()
|
||||
const exceptions = [
|
||||
"of",
|
||||
"and",
|
||||
"in",
|
||||
"the",
|
||||
"with",
|
||||
"on",
|
||||
"at",
|
||||
"by",
|
||||
"from",
|
||||
"to",
|
||||
"a",
|
||||
"an",
|
||||
"for",
|
||||
]
|
||||
|
||||
return str.replace(/\b\w+(-\w+)*\b/g, (txt: string): string => {
|
||||
return txt
|
||||
.split("-")
|
||||
.map((word, index) => {
|
||||
if (exceptions.includes(word.toLowerCase()) && index !== 0) {
|
||||
return word.toLowerCase()
|
||||
}
|
||||
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
|
||||
})
|
||||
.join("-")
|
||||
})
|
||||
}
|
||||
|
||||
@ -13,10 +37,14 @@ export const mapFn: Options["mapFn"] = (node) => {
|
||||
if (node.file) {
|
||||
if (node.file.relativePath?.includes("daily/")) {
|
||||
node.displayName = "🗓️ " + node.displayName
|
||||
}
|
||||
if (node.file.relativePath?.includes("references/")) {
|
||||
const parts = node.file.frontmatter?.title?.split("::") ?? []
|
||||
node.displayName = "📚 " + (parts.length > 1 ? parts[1].trim() : parts[0]?.trim() || "")
|
||||
} else if (node.name == "movies") {
|
||||
node.displayName = "🎬 " + node.displayName
|
||||
node.displayName = "🎬 " + node.file.frontmatter?.title
|
||||
} else {
|
||||
node.displayName = "📄 " + node.displayName
|
||||
node.displayName = "📄 " + node.file.frontmatter?.title
|
||||
}
|
||||
} else {
|
||||
node.displayName = "📁 " + toTitleCase(node.displayName)
|
||||
|
||||
@ -25,7 +25,7 @@ const config: QuartzConfig = {
|
||||
typography: {
|
||||
header: "Open Sans",
|
||||
body: "Open Sans",
|
||||
code: "Space Mono",
|
||||
code: "Roboto Mono",
|
||||
},
|
||||
colors: {
|
||||
lightMode: {
|
||||
@ -70,10 +70,10 @@ const config: QuartzConfig = {
|
||||
}),
|
||||
Plugin.SyntaxHighlighting({
|
||||
theme: {
|
||||
light: "github-light",
|
||||
dark: "dracula",
|
||||
light: "catppuccin-latte",
|
||||
dark: "tokyo-night",
|
||||
},
|
||||
keepBackground: false,
|
||||
keepBackground: true,
|
||||
}),
|
||||
Plugin.TableOfContents({
|
||||
showByDefault: true,
|
||||
|
||||
@ -19,12 +19,18 @@ export const sharedPageComponents: SharedLayout = {
|
||||
// components for pages that display a single page (e.g. a single note)
|
||||
export const defaultContentPageLayout: PageLayout = {
|
||||
beforeBody: [
|
||||
Component.Breadcrumbs({ rootName: "Index" }),
|
||||
Component.CollapsibleHeaders(),
|
||||
Component.Breadcrumbs({
|
||||
rootName: "Index",
|
||||
showCurrentPage: false,
|
||||
}),
|
||||
Component.ArticleTitle(),
|
||||
Component.TagList(),
|
||||
Component.ContentMeta({
|
||||
showReadingTime: false,
|
||||
showFootnoteLink: true,
|
||||
showComma: true,
|
||||
}),
|
||||
Component.TagList(),
|
||||
],
|
||||
left: [
|
||||
Component.PageTitle(),
|
||||
@ -33,6 +39,7 @@ export const defaultContentPageLayout: PageLayout = {
|
||||
Component.Darkmode(),
|
||||
Component.DesktopOnly(
|
||||
Component.Explorer({
|
||||
title: "Notes",
|
||||
mapFn: mapFn,
|
||||
sortFn: sortFn,
|
||||
}),
|
||||
|
||||
@ -13,7 +13,7 @@ const Backlinks: QuartzComponent = ({
|
||||
const slug = simplifySlug(fileData.slug!)
|
||||
const backlinkFiles = allFiles.filter((file) => file.links?.includes(slug))
|
||||
return (
|
||||
<div class={classNames(displayClass, "backlinks")}>
|
||||
<div id="backlinks" class={classNames(displayClass, "backlinks")}>
|
||||
<h3>{i18n(cfg.locale).components.backlinks.title}</h3>
|
||||
<ul class="overflow">
|
||||
{backlinkFiles.length > 0 ? (
|
||||
|
||||
47
quartz/components/CollapsibleHeaders.tsx
Normal file
47
quartz/components/CollapsibleHeaders.tsx
Normal file
@ -0,0 +1,47 @@
|
||||
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
|
||||
|
||||
export default (() => {
|
||||
function CollapsibleHeaders({ displayClass }: QuartzComponentProps) {
|
||||
return <div class={`collapsible-headers ${displayClass ?? ""}`}></div>
|
||||
}
|
||||
|
||||
CollapsibleHeaders.afterDOMLoaded = `
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const headers = document.querySelectorAll('h2, h3, h4, h5, h6');
|
||||
|
||||
headers.forEach(header => {
|
||||
// Add click event listener to each header
|
||||
header.addEventListener('click', function() {
|
||||
this.classList.toggle('collapsed');
|
||||
let currentElement = this.nextElementSibling;
|
||||
|
||||
while (currentElement && !['H2', 'H3', 'H4', 'H5', 'H6'].includes(currentElement.tagName)) {
|
||||
if (currentElement.style.display === 'none') {
|
||||
currentElement.style.display = '';
|
||||
} else {
|
||||
currentElement.style.display = 'none';
|
||||
}
|
||||
currentElement = currentElement.nextElementSibling;
|
||||
}
|
||||
});
|
||||
|
||||
// Add visual cue that header is clickable
|
||||
header.style.cursor = 'pointer';
|
||||
});
|
||||
});
|
||||
`
|
||||
|
||||
CollapsibleHeaders.css = `
|
||||
h2, h3, h4, h5, h6 {
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
.collapsed + * {
|
||||
display: none;
|
||||
}
|
||||
.collapsed {
|
||||
opacity: 0.6;
|
||||
}
|
||||
`
|
||||
|
||||
return CollapsibleHeaders
|
||||
}) satisfies QuartzComponentConstructor
|
||||
@ -8,11 +8,15 @@ import style from "./styles/contentMeta.scss"
|
||||
|
||||
interface ContentMetaOptions {
|
||||
showReadingTime: boolean
|
||||
showBacklinkLink: boolean
|
||||
showFootnoteLink: boolean
|
||||
showComma: boolean
|
||||
}
|
||||
|
||||
const defaultOptions: ContentMetaOptions = {
|
||||
showReadingTime: true,
|
||||
showBacklinkLink: true,
|
||||
showFootnoteLink: true,
|
||||
showComma: true,
|
||||
}
|
||||
|
||||
@ -81,6 +85,26 @@ export default ((opts?: Partial<ContentMetaOptions>) => {
|
||||
segments.push(displayedTime)
|
||||
}
|
||||
|
||||
// Display link to footnotes if enabled
|
||||
if (options.showFootnoteLink) {
|
||||
const footnoteLinkSegment = (
|
||||
<a href="#footnotes" title="Convenience link to the footnotes.">
|
||||
footnotes
|
||||
</a>
|
||||
)
|
||||
segments.push(footnoteLinkSegment)
|
||||
}
|
||||
|
||||
// Display link to backlinks if enabled
|
||||
if (options.showBacklinkLink) {
|
||||
const backlinkSegment = (
|
||||
<a href="#backlinks" title="Convenience link to the footnotes.">
|
||||
backlinks
|
||||
</a>
|
||||
)
|
||||
segments.push(backlinkSegment)
|
||||
}
|
||||
|
||||
const segmentsElements = segments.map((segment) => <span>{segment}</span>)
|
||||
|
||||
return (
|
||||
|
||||
@ -19,6 +19,7 @@ import DesktopOnly from "./DesktopOnly"
|
||||
import MobileOnly from "./MobileOnly"
|
||||
import RecentNotes from "./RecentNotes"
|
||||
import Breadcrumbs from "./Breadcrumbs"
|
||||
import CollapsibleHeaders from "./CollapsibleHeaders"
|
||||
|
||||
export {
|
||||
ArticleTitle,
|
||||
@ -42,4 +43,5 @@ export {
|
||||
RecentNotes,
|
||||
NotFound,
|
||||
Breadcrumbs,
|
||||
CollapsibleHeaders,
|
||||
}
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
.content-meta {
|
||||
margin-top: 0;
|
||||
font-weight: bold;
|
||||
margin-top: 0.25em;
|
||||
color: var(--gray);
|
||||
|
||||
&[show-comma="true"] {
|
||||
> span:not(:last-child) {
|
||||
margin-right: 8px;
|
||||
margin-right: 0.75em;
|
||||
|
||||
&::after {
|
||||
content: ",";
|
||||
content: "·";
|
||||
margin-left: 0.75em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,7 +131,7 @@ a {
|
||||
|
||||
& article {
|
||||
& > h1 {
|
||||
font-size: 1.75rem;
|
||||
font-size: 1.65rem;
|
||||
}
|
||||
|
||||
& li:has(> input[type="checkbox"]) {
|
||||
@ -413,7 +413,7 @@ pre {
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.9em;
|
||||
font-size: 1.0em;
|
||||
color: var(--dark);
|
||||
font-family: var(--codeFont);
|
||||
border-radius: 5px;
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
|
||||
.tag {
|
||||
float: right;
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
color: var(--theme);
|
||||
}
|
||||
|
||||
@ -103,6 +103,7 @@ p.timestamp-wrapper {
|
||||
}
|
||||
|
||||
/* Base styles */
|
||||
|
||||
.jvc {
|
||||
margin-left: var(--base-indent);
|
||||
}
|
||||
@ -277,10 +278,72 @@ article.popover-hint::after {
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
/* Metadata */
|
||||
/* Metadata + Title */
|
||||
|
||||
.article-title {
|
||||
font-size: 1.15em;
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
p.content-meta a {
|
||||
/* your styles here */
|
||||
color: var(--gray); /* example: change link color */
|
||||
text-decoration: underline; /* example: underline on hover */
|
||||
color: var(--gray);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Explorer */
|
||||
|
||||
#explorer-content {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
/* Details */
|
||||
|
||||
details {
|
||||
border: 1px solid var(--lightgray);
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
background-color: var(--light);
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
/* style the summary element */
|
||||
summary {
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
padding: 5px 0;
|
||||
color: var(--darkgray);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* add a transition effect for the summary element when focused */
|
||||
summary:focus {
|
||||
color: var(--secondary);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* add a hover effect for the summary element */
|
||||
summary:hover {
|
||||
color: var(--secondary);
|
||||
}
|
||||
|
||||
/* additional style for the details content */
|
||||
details[open] {
|
||||
border-color: var(--secondary);
|
||||
background-color: var(--highlight);
|
||||
}
|
||||
|
||||
/* optional: add an icon before the summary text */
|
||||
summary::before {
|
||||
content: "➕ ";
|
||||
font-size: 0.8em;
|
||||
margin-right: 5px;
|
||||
transition: transform 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
/* rotate the icon when the details element is open */
|
||||
details[open] summary::before {
|
||||
transform: rotate(45deg);
|
||||
content: "➖ ";
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user