feat(callouts): make callouts look like Obsidian callouts

- change callout look
- make callouts collapsible (https://github.com/oleeskild/obsidian-digital-garden/issues/89)
This commit is contained in:
Luke-zhang-04 2023-01-11 17:45:01 -05:00 committed by Ole Eskild Steensen
parent 00011e734e
commit f328f9b411
4 changed files with 201 additions and 364 deletions

View File

@ -183,28 +183,30 @@ module.exports = function(eleventyConfig) {
let titleDiv = "";
let calloutType = "";
const calloutMeta = /\[!(\w*)\](\s?.*)/;
let isCollapsable;
let isCollapsed;
const calloutMeta = /\[!(\w*)\](\+|\-){0,1}(\s?.*)/;
if (!content.match(calloutMeta)) {
continue;
}
content = content.replace(calloutMeta, function(metaInfoMatch, callout, title) {
content = content.replace(calloutMeta, function(metaInfoMatch, callout, collapse, title) {
isCollapsable = Boolean(collapse);
isCollapsed = collapse === "-"
const titleText = title.replace(/(<\/{0,1}\w+>)/, "") ? title : `${callout.charAt(0).toUpperCase()}${callout.substring(1).toLowerCase()}`
const fold = isCollapsable ? `<div class="callout-fold"><i icon-name="chevron-down"></i></div>` : ``
calloutType = callout;
titleDiv = title.replace("<br>", "") ?
`<div class="admonition-title">${title}</div>` :
`<div class="admonition-title">${callout.charAt(0).toUpperCase()}${callout.substring(1).toLowerCase()}</div>`;
titleDiv = `<div class="callout-title"><div class="callout-title-inner">${titleText}</div>${fold}</div>`
return "";
});
blockquote.tagName = "div";
blockquote.classList.add(
`callout-${calloutType.toLowerCase()}`,
"admonition",
"admonition-example",
"admonition-plugin",
);
blockquote.classList.add("callout");
blockquote.classList.add(isCollapsable ? "is-collapsible" : "")
blockquote.classList.add(isCollapsed ? "is-collapsed" : "")
blockquote.setAttribute("data-callout", calloutType.toLowerCase());
blockquote.innerHTML = `${titleDiv}\n${content}`;
blockquote.innerHTML = `${titleDiv}\n<div class="callout-content">${content}</div>`;
}
}

View File

@ -1,5 +1,42 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://unpkg.com/mermaid/dist/mermaid.min.js"></script>
<script src="https://unpkg.com/lucide@0"></script>
<script>
// Create callout icons
window.addEventListener("load", () => {
document.querySelectorAll(".callout").forEach((elem) => {
const icon = getComputedStyle(elem).getPropertyValue('--callout-icon');
const iconName = icon && icon.replace(/^lucide-/, "");
if (iconName) {
const calloutTitle = elem.querySelector(".callout-title");
if (calloutTitle) {
const calloutIconContainer = document.createElement("div");
const calloutIcon = document.createElement("i");
calloutIconContainer.appendChild(calloutIcon);
calloutIcon.setAttribute("icon-name", iconName);
calloutIconContainer.setAttribute("class", "callout-icon");
calloutTitle.insertBefore(calloutIconContainer, calloutTitle.firstChild);
}
}
});
lucide.createIcons();
// Collapse callouts
Array.from(document.querySelectorAll(".callout.is-collapsible")).forEach((elem) => {
elem.addEventListener("click", (event) => {
if (elem.classList.contains("is-collapsed")) {
elem.classList.remove("is-collapsed");
} else {
elem.classList.add("is-collapsed");
}
});
});
});
</script>
<script>
mermaid.initialize({
startOnLoad: true,

View File

@ -506,365 +506,37 @@ ul.task-list {
}
}
div[class*="language-ad-"],
div[class*="callout-"] {
font-family: 'Roboto', sans-serif;
word-wrap: break-word;
border-radius: 6px;
display: block;
font-size: 1rem;
margin-top: 1rem;
outline-color: rgb(230, 230, 230);
padding: 1rem;
position: relative;
transition: height .5s ease-in, opacity .5s ease-in;
word-break: break-word;
white-space: normal !important;
.callout-title-inner,
.callout-title-inner p,
.callout-icon,
.callout-fold,
.callout-content {
margin: 0;
padding: 0;
}
.header-tags {
display: flex;
flex-wrap: wrap;
margin-top: 10px;
gap: 5px;
.callout-title {
margin-top: 0;
align-items: center;
}
.header-meta {
margin-bottom: 10px;
.callout {
font-family: "Roboto", sans-serif;
word-wrap: break-word;
display: block;
font-size: 1rem;
}
div.language-ad-note,
div.callout-note {
.admonition-title::before {
content: "🖊️";
.callout.is-collapsed {
.callout-content {
display: none;
}
.callout-fold .lucide {
transform: rotate(-90deg);
}
}
div.language-ad-tip,
div.callout-tip {
.admonition-title::before {
content: "💡";
}
}
div.language-ad-warning,
div.callout-warning {
.admonition-title::before {
content: "⚠️";
}
}
div.language-ad-important,
div.callout-important {
.admonition-title::before {
content: "❗️";
}
}
div.language-ad-caution,
div.callout-caution {
.admonition-title::before {
content: "⚠️";
}
}
div.language-ad-info,
div.callout-info {
.admonition-title::before {
content: "";
}
}
div.language-ad-example,
div.callout-example {
.admonition-title::before {
content: "🗒️";
}
}
div.language-ad-seealso,
div.callout-seealso {
.admonition-title::before {
content: "🖊️";
}
}
div.language-ad-abstract,
div.callout-abstract {
.admonition-title::before {
content: '📚'
}
}
div.language-ad-summary,
div.callout-summary {
.admonition-title::before {
content: '📚'
}
}
div.language-ad-tldr,
div.callout-tldr {
.admonition-title::before {
content: '📚'
}
}
div.language-ad-todo,
div.callout-todo {
.admonition-title::before {
content: '☑️'
}
}
div.language-ad-hint,
div.callout-hint {
.admonition-title::before {
content: '🔥'
}
}
div.language-ad-success,
div.callout-success {
.admonition-title::before {
content:
}
}
div.language-ad-check,
div.callout-check {
.admonition-title::before {
content: ''
}
}
div.language-ad-done,
div.callout-done {
.admonition-title::before {
content: ''
}
}
div.language-ad-question,
div.callout-question {
.admonition-title::before {
content: ''
}
}
div.language-ad-help,
div.callout-help {
.admonition-title::before {
content: ''
}
}
div.language-ad-faq,
div.callout-faq {
.admonition-title::before {
content: ''
}
}
div.language-ad-attention,
div.callout-attention {
.admonition-title::before {
content: '⚠️'
}
}
div.language-ad-failure,
div.callout-failure {
.admonition-title::before {
content: ''
}
}
div.language-ad-fail,
div.callout-fail {
.admonition-title::before {
content: ''
}
}
div.language-ad-missing,
div.callout-missing {
.admonition-title::before {
content: ''
}
}
div.language-ad-danger,
div.callout-danger {
.admonition-title::before {
content: ''
}
}
div.language-ad-error,
div.callout-error {
.admonition-title::before {
content: ''
}
}
div.language-ad-bug,
div.callout-bug {
.admonition-title::before {
content: '🐞'
}
}
div.language-ad-quote,
div.callout-quote {
.admonition-title::before {
content: '💬'
}
}
div.language-ad-cite,
div.callout-cite {
.admonition-title::before {
content: '💬'
}
}
div.language-ad-note,
div.callout-note {
background-color: rgba(68, 138, 255, .5)
}
div.language-ad-seealso,
div.callout-seealso {
background-color: rgba(68, 138, 255, .5)
}
div.language-ad-abstract,
div.callout-abstract {
background-color: rgba(0, 176, 255, .5)
}
div.language-ad-summary,
div.callout-summary {
background-color: rgba(0, 176, 255, .5)
}
div.language-ad-tldr,
div.callout-tldr {
background-color: rgba(0, 176, 255, .5)
}
div.language-ad-info,
div.callout-info {
background-color: rgba(0, 184, 212, .5)
}
div.language-ad-todo,
div.callout-todo {
background-color: rgba(0, 184, 212, .5)
}
div.language-ad-tip,
div.callout-tip {
background-color: rgba(0, 191, 165, .5)
}
div.language-ad-hint,
div.callout-hint {
background-color: rgba(0, 191, 165, .5)
}
div.language-ad-important,
div.callout-important {
background-color: rgba(0, 191, 165, .5)
}
div.language-ad-success,
div.callout-success {
background-color: rgba(0, 200, 83, .5)
}
div.language-ad-check,
div.callout-check {
background-color: rgba(0, 200, 83, .5)
}
div.language-ad-done,
div.callout-done {
background-color: rgba(0, 200, 83, .5)
}
div.language-ad-question,
div.callout-question {
background-color: rgba(100, 221, 23, .5)
}
div.language-ad-help,
div.callout-help {
background-color: rgba(100, 221, 23, .5)
}
div.language-ad-faq,
div.callout-faq {
background-color: rgba(100, 221, 23, .5)
}
div.language-ad-warning,
div.callout-warning {
background-color: rgba(255, 145, 0, .5)
}
div.language-ad-caution,
div.callout-caution {
background-color: rgba(255, 145, 0, .5)
}
div.language-ad-attention,
div.callout-attention {
background-color: rgba(255, 145, 0, .5)
}
div.language-ad-failure,
div.callout-failure {
background-color: rgba(255, 82, 82, .5)
}
div.language-ad-fail,
div.callout-fail {
background-color: rgba(255, 82, 82, .5)
}
div.language-ad-missing,
div.callout-missing {
background-color: rgba(255, 82, 82, .5)
}
div.language-ad-danger,
div.callout-danger {
background-color: rgba(255, 23, 68, .5)
}
div.language-ad-error,
div.callout-error {
background-color: rgba(255, 23, 68, .5)
}
div.language-ad-bug,
div.callout-bug {
background-color: rgba(245, 0, 87, .5)
}
div.language-ad-example,
div.callout-example {
background-color: rgba(124, 77, 255, .5)
}
div.language-ad-quote,
div.callout-quote {
background-color: rgba(158, 158, 158, .5)
}
div.language-ad-cite,
div.callout-cite {
background-color: rgba(158, 158, 158, .5)
.callout-fold .lucide {
transition: transform 100ms ease-in-out;
}

View File

@ -10,6 +10,15 @@
--text-normal: #dcddde;
--text-accent: rgb(97, 186, 245);
--file-margins: 32px;
--callout-border-width: 0px;
--callout-border-opacity: 0.25;
--callout-padding: 12px 12px 12px 24px;
--callout-radius: 4px;
--callout-blend-mode: lighten;
--callout-title-padding: 0;
--callout-title-size: inherit;
--callout-content-padding: 0;
}
h1 {
@ -92,3 +101,120 @@ p>code {
color: #c7254e;
background-color: #1a1a1a;
}
.callout {
--callout-color: 68, 138, 255;
--callout-icon: lucide-pencil;
}
.callout[data-callout="abstract"],
.callout[data-callout="summary"],
.callout[data-callout="tldr"] {
--callout-color: 0, 176, 255;
--callout-icon: lucide-clipboard-list;
}
.callout[data-callout="info"],
.callout[data-callout="todo"] {
--callout-color: 0, 184, 212;
}
.callout[data-callout="info"] {
--callout-icon: lucide-info;
}
.callout[data-callout="todo"] {
--callout-icon: lucide-check-circle-2;
}
.callout[data-callout="tip"],
.callout[data-callout="hint"],
.callout[data-callout="important"] {
--callout-color: 0, 191, 165;
--callout-icon: lucide-flame;
}
.callout[data-callout="success"],
.callout[data-callout="check"],
.callout[data-callout="done"] {
--callout-color: 0, 200, 83;
--callout-icon: lucide-check;
}
.callout[data-callout="question"],
.callout[data-callout="help"],
.callout[data-callout="faq"] {
--callout-color: 100, 221, 23;
--callout-icon: help-circle;
}
.callout[data-callout="warning"],
.callout[data-callout="caution"],
.callout[data-callout="attention"] {
--callout-color: 255, 145, 0;
--callout-icon: lucide-alert-triangle;
}
.callout[data-callout="failure"],
.callout[data-callout="fail"],
.callout[data-callout="missing"] {
--callout-color: 255, 82, 82;
--callout-icon: lucide-x;
}
.callout[data-callout="danger"],
.callout[data-callout="error"] {
--callout-color: 255, 23, 68;
--callout-icon: lucide-zap;
}
.callout[data-callout="bug"] {
--callout-color: 245, 0, 87;
--callout-icon: lucide-bug;
}
.callout[data-callout="example"] {
--callout-color: 124, 77, 255;
--callout-icon: lucide-list;
}
.callout[data-callout="quote"],
.callout[data-callout="cite"] {
--callout-color: 158, 158, 158;
--callout-icon: quote-glyph;
}
.callout {
overflow: hidden;
border-style: solid;
border-color: rgba(var(--callout-color), var(--callout-border-opacity));
border-width: var(--callout-border-width);
border-radius: var(--callout-radius);
margin: 1em 0;
mix-blend-mode: var(--callout-blend-mode);
background-color: rgba(var(--callout-color), 0.1);
padding: var(--callout-padding);
}
.callout.is-collapsible .callout-title {
cursor: default;
}
.callout-title {
padding: var(--callout-title-padding);
display: flex;
gap: 4px;
font-size: var(--callout-title-size);
color: rgb(var(--callout-color));
line-height: 1.3;
}
.callout-content {
overflow-x: auto;
padding: var(--callout-content-padding);
}
.callout-icon {
flex: 0 0 auto;
display: flex;
align-self: center;
}
.callout-icon .svg-icon {
color: rgb(var(--callout-color));
}
.callout-title-inner {
font-weight: 600;
}
.callout-fold {
display: flex;
align-items: center;
padding-right: 8px;
}
.callout-fold .svg-icon {
transition: transform 100ms ease-in-out;
}
.callout.is-collapsed .callout-fold .svg-icon {
transform: rotate(-90deg);
}