Skip to content

Commit

Permalink
feat!: Admonitions now mimics the structure of callouts
Browse files Browse the repository at this point in the history
  • Loading branch information
valentine195 committed Mar 31, 2022
1 parent 4776da3 commit 1ba0085
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 243 deletions.
2 changes: 1 addition & 1 deletion src/@types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface Admonition {
command: boolean;
injectColor: boolean;
noTitle: boolean;
copy: boolean;
copy?: boolean;
}

export interface NestedAdmonition {
Expand Down
111 changes: 12 additions & 99 deletions src/assets/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,6 @@
.admonition {
margin-top: var(--admonition-margin-top);
margin-bottom: var(--admonition-margin-bottom);
margin-left: 0;
margin-right: 0;
padding: 0;
overflow: hidden;
color: var(--text-normal);
page-break-inside: avoid;
background-color: var(--background-secondary);
border-left: 0.2rem solid rgb(var(--admonition-color));
border-radius: 0.1rem;
box-shadow: 0 0.2rem 0.5rem var(--background-modifier-box-shadow);
}

Expand All @@ -29,61 +20,28 @@
opacity: 0.1;
}

.admonition-title {
position: relative;
padding: 0.6rem 0.25em;
font-weight: 700;
background-color: rgba(var(--admonition-color), 0.1);
}

.admonition-title-content {
display: flex;
justify-content: flex-start;
margin-top: 0 !important;
margin-bottom: 0 !important;
}

.admonition-title-icon {
color: rgb(var(--admonition-color));
display: flex;
align-items: center;
justify-content: center;
margin: 0 0.5em 0 0.25em;
min-width: 1em;
width: min-content;
}

.admonition-title-markdown {
display: block;
}

.admonition-title.no-title {
display: none;
}

.admonition-plugin.no-title .admonition-content-holder,
.admonition-plugin.no-title .admonition-content-holder > .admonition-content {
margin-top: 0;
margin-bottom: 0;
}

.admonition-content-holder {
.admonition-content,
.callout-content {
position: relative;
}

.admonition-content {
margin: 10px 15px;
position: relative;
overflow-x: auto;
.admonition.no-title .admonition-content {
margin-top: 0;
margin-bottom: 0;
}

.admonition-content-copy {
color: var(--text-faint);
cursor: pointer;
opacity: 0;
position: absolute;
right: 0.375rem;
top: -5px;
margin: 0.375rem;
right: 0;
top: 0;
transition: 0.3s opacity ease-in;
}

Expand All @@ -92,59 +50,14 @@
}

.admonition:hover .admonition-content-copy,
.callout:hover .admonition-content-copy,
.admonition-content-copy:hover {
opacity: 1;
}
.admonition-title:hover + .admonition-content .admonition-content-copy {
opacity: 0;
}

details.admonition:not([open]) {
padding-bottom: 0;
}

details.admonition > summary {
outline: none;
display: block !important;
list-style: none !important;
list-style-type: none !important;
min-height: 1rem;
border-top-left-radius: 0.1rem;
border-top-right-radius: 0.1rem;
cursor: pointer;
}

details.admonition > summary::-webkit-details-marker,
details.admonition > summary::marker {
display: none !important;
}

details.admonition > summary > .collapser {
position: absolute;
top: 50%;
right: 8px;
transform: translateY(-50%);
content: "";
}

details.admonition > summary > .collapser > .handle {
transform: rotate(0deg);
transition: transform 0.25s;
background-color: currentColor;
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: contain;
mask-size: contain;
-webkit-mask-image: var(--admonition-details-icon);
mask-image: var(--admonition-details-icon);
width: 20px;
height: 20px;
}

details.admonition[open] > summary > .collapser > .handle {
transform: rotate(90deg);
}

/** Settings */
.admonition-settings .additional {
margin: 6px 12px;
Expand Down Expand Up @@ -360,19 +273,19 @@ input.is-invalid {
.admonition.no-drop {
box-shadow: none;
}
.admonition.no-drop > .admonition-title.no-title + .admonition-content-holder {
.admonition.no-drop > .admonition-title.no-title + .admonition-content {
margin-top: 0;
margin-bottom: 0;
}

.admonition.no-drop .admonition .admonition-content-holder {
.admonition.no-drop .admonition .admonition-content {
border-right: 1px solid rgba(var(--admonition-color), 0.2);
border-bottom: 1px solid rgba(var(--admonition-color), 0.2);
}
.admonition.no-drop
.admonition
.admonition-title.no-title
+ .admonition-content-holder {
+ .admonition-content {
border-top: 1px solid rgba(var(--admonition-color), 0.2);
margin-top: 0;
margin-bottom: 0;
Expand Down
152 changes: 92 additions & 60 deletions src/callout/manager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
addIcon,
Component,
MarkdownPostProcessorContext,
Notice,
setIcon
} from "obsidian";
import { Admonition } from "src/@types";
Expand Down Expand Up @@ -52,24 +52,46 @@ export default class CalloutManager extends Component {
const callout = el?.querySelector<HTMLDivElement>(".callout");
if (!callout) return;
//apply metadata

const type = callout.dataset.callout;
const admonition = this.plugin.admonitions[type];
if (!admonition) return;

const titleEl = callout.querySelector<HTMLDivElement>(".callout-title");
const content =
callout.querySelector<HTMLDivElement>(".callout-content");

const section = ctx.getSectionInfo(el);
if (section) {
const { text, lineStart } = section;
const { text, lineStart, lineEnd } = section;
const definition = text.split("\n")[lineStart];

const [, metadata] = definition.match(/> \[!.+\|(.*)]/) ?? [];
if (metadata) {
callout.dataset.calloutMetadata = metadata;
}
}

const type = callout.dataset.callout;
const admonition = this.plugin.data.userAdmonitions[type];
if (!admonition) return;

const titleEl = callout.querySelector<HTMLDivElement>(".callout-title");
const content =
callout.querySelector<HTMLDivElement>(".callout-content");
if (
this.plugin.admonitions[type].copy ??
this.plugin.data.copyButton
) {
let copy = content.createDiv("admonition-content-copy");
setIcon(copy, "copy");
copy.addEventListener("click", () => {
navigator.clipboard
.writeText(
text
.split("\n")
.slice(lineStart + 1, lineEnd + 1)
.join("\n")
.replace(/^> /gm, "")
)
.then(async () => {
new Notice("Callout content copied to clipboard.");
});
});
}
}

if (admonition.noTitle && !callout.dataset.calloutFold) {
titleEl.addClass("no-title");
Expand All @@ -79,53 +101,7 @@ export default class CalloutManager extends Component {
this.plugin.data.autoCollapse &&
!callout.dataset.calloutFold
) {
if (!content) return;
callout.addClass("is-collapsible");
if (this.plugin.data.defaultCollapseType == "closed") {
callout.dataset.calloutFold = "-";
callout.addClass("is-collapsed");
} else {
callout.dataset.calloutFold = "+";
}

const iconEl = titleEl.createDiv("callout-fold");

setIcon(iconEl, "chevron-down");

let collapsed = callout.hasClass("is-collapsed");

this.getComputedHeights(content);

if (collapsed) {
for (const prop of this.heights) {
content.style.setProperty(prop, "0px");
}
}
titleEl.onclick = (event: MouseEvent) => {
event.preventDefault();

function transitionEnd(evt: TransitionEvent) {
content.removeEventListener("transitionend", transitionEnd);
content.style.removeProperty("transition");
}
content.addEventListener("transitionend", transitionEnd);
content.style.setProperty(
"transition",
"all 100ms cubic-bezier(.02, .01, .47, 1)"
);
collapsed = callout.hasClass("is-collapsed");
if (event.button == 0) {
for (const prop of this.heights) {
const heights = this.getComputedHeights(content);
content.style.setProperty(
prop,
collapsed ? heights[prop] : "0px"
);
}

callout.toggleClass("is-collapsed", !collapsed);
}
};
this.setCollapsible(callout);
}

if (
Expand All @@ -144,6 +120,61 @@ export default class CalloutManager extends Component {
callout.addClass("drop-shadow");
}
}

setCollapsible(callout: HTMLElement) {
const titleEl = callout.querySelector<HTMLDivElement>(".callout-title");
const content =
callout.querySelector<HTMLDivElement>(".callout-content");

if (!content) return;
callout.addClass("is-collapsible");
if (this.plugin.data.defaultCollapseType == "closed") {
callout.dataset.calloutFold = "-";
callout.addClass("is-collapsed");
} else {
callout.dataset.calloutFold = "+";
}

const iconEl = titleEl.createDiv("callout-fold");

setIcon(iconEl, "chevron-down");

let collapsed = callout.hasClass("is-collapsed");

this.getComputedHeights(content);

if (collapsed) {
for (const prop of this.heights) {
content.style.setProperty(prop, "0px");
}
}
titleEl.onclick = (event: MouseEvent) => {
event.preventDefault();

function transitionEnd(evt: TransitionEvent) {
content.removeEventListener("transitionend", transitionEnd);
content.style.removeProperty("transition");
}
content.addEventListener("transitionend", transitionEnd);
content.style.setProperty(
"transition",
"all 100ms cubic-bezier(.02, .01, .47, 1)"
);
collapsed = callout.hasClass("is-collapsed");
if (event.button == 0) {
for (const prop of this.heights) {
const heights = this.getComputedHeights(content);
content.style.setProperty(
prop,
collapsed ? heights[prop] : "0px"
);
}

callout.toggleClass("is-collapsed", !collapsed);
}
};
}

getComputedHeights(el: HTMLDivElement): Heights {
if (this.heightMap.has(el)) {
return this.heightMap.get(el);
Expand Down Expand Up @@ -176,9 +207,10 @@ export default class CalloutManager extends Component {
} else {
rule = `.callout[data-callout="${admonition.type}"] {
--callout-color: ${admonition.color};
--callout-icon: '${(this.plugin.iconManager
.getIconNode(admonition.icon)
?.outerHTML ?? "").replace(/(width|height)=(\\?"|')\d+(\\?"|')/g, "")}';
--callout-icon: '${(
this.plugin.iconManager.getIconNode(admonition.icon)?.outerHTML ??
""
).replace(/(width|height)=(\\?"|')\d+(\\?"|')/g, "")}';
}`;
}
if (this.indexing.contains(admonition.type)) {
Expand Down
Loading

0 comments on commit 1ba0085

Please sign in to comment.