Skip to content

Commit

Permalink
0.1.0
Browse files Browse the repository at this point in the history
Removed admonition.ts
Added fastIntersection function
Updated documentation
  • Loading branch information
valentine195 committed Mar 23, 2021
1 parent 53c0515 commit f506641
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 124 deletions.
35 changes: 26 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Obsidian Admonition

Adds admonition block-styled content to Obsidian.md
Adds admonition block-styled content to Obsidian.md, styled after [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/reference/admonitions/)

![](https://raw.githubusercontent.com/valentine195/obsidian-admonition/master/images/all.gif)

## Usage

Expand All @@ -12,9 +14,19 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla.
```
````

This will then render as the admonition:
Becomes:

![](https://raw.githubusercontent.com/valentine195/obsidian-admonition/master/images/default.png)

<img src="https://i.imgur.com/295CZkD.png">
## Options

````markdown
```<type> # Admonition type. See below for a list of available types.
title: # Admonition title. Leave blank to remove the title element and display only the content.
collapse: # Create a collapsible admonition. Use "open" to initially render the admonition open.
content: # Actual text of admonition. Only required if "title" or "collapse" is used.
```
````

### Titles

Expand All @@ -27,27 +39,32 @@ content: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euism
```
````

<img src="https://i.imgur.com/pBTJAFa.png">
![](https://raw.githubusercontent.com/valentine195/obsidian-admonition/master/images/title.png)

Leave the title field blank to only display the admonition.

````markdown
```note
title:
content: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla.
```
````

<img src="https://i.imgur.com/pNU2MB7.png">
![](https://raw.githubusercontent.com/valentine195/obsidian-admonition/master/images/no-title.png)

**Please note that when the title is included, you _must_ specificy the content as well.**
**Please note that when the title is included, you _must_ specify the content as well.**

### Collapsible

Use `collapse: open` or `collapse: closed` to create a collapsible admonition.
Use the `collapse` parameter to create a collapsible admonition.

`collapse: open` will start the admonition opened on render, but allow collapse on click.

If a blank title is provided, the collapse parameter will not do anything.

`collapse: open` will startthe admonition opened on render.
![](https://raw.githubusercontent.com/valentine195/obsidian-admonition/master/images/collapse.gif)

<img width='640px' src="https://thumbs.gfycat.com/UniqueVillainousHarpseal-size_restricted.gif">
**Please note that when the title is included, you _must_ specify the content as well.**

## Admonition Types

Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "obsidian-admonition",
"name": "Admonition",
"version": "0.0.5",
"version": "0.1.0",
"minAppVersion": "0.11.0",
"description": "Admonition block-styled content for Obsidian.md",
"author": "Jeremy Valentine",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "obsidian-admonition",
"version": "0.0.5",
"version": "0.1.0",
"description": "Admonition block-styled content for Obsidian.md",
"main": "main.js",
"scripts": {
Expand Down
63 changes: 0 additions & 63 deletions src/admonitions.ts

This file was deleted.

147 changes: 98 additions & 49 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,112 @@
import { MarkdownPostProcessorContext, Plugin } from "obsidian";
import { MarkdownPostProcessorContext, Notice, Plugin } from "obsidian";

import "./main.css";
import ADMONITION_MAP from "./admonitions";

export default class Admonition extends Plugin {
const ADMONITION_MAP: {
[admonitionType: string]: string;
} = {
note: "note",
seealso: "note",
abstract: "abstract",
summary: "abstract",
info: "info",
todo: "todo",
tip: "tip",
hint: "tip",
important: "tip",
success: "success",
check: "check",
done: "done",
question: "question",
help: "question",
faq: "question",
warning: "warning",
caution: "warning",
attention: "warning",
failure: "failure",
fail: "failure",
missing: "failure",
danger: "danger",
error: "danger",
bug: "bug",
example: "example",
quote: "quote",
cite: "quote"
};
const classMap = Object.keys(ADMONITION_MAP).map((k) => `language-${k}`);

/** Fast Intersection taken from
* https://codeburst.io/optimizing-array-analytics-in-javascript-part-two-search-intersection-and-cross-products-79b4a6d68da0
*/
const fastIntersection = (...arrays: any[]) => {
// if we process the arrays from shortest to longest
// then we will identify failure points faster, i.e. when
// one item is not in all arrays
const ordered =
arrays.length === 1
? arrays
: arrays.sort((a1, a2) => a1.length - a2.length),
shortest = ordered[0],
set = new Set(), // used for bookeeping, Sets are faster
result = []; // the intersection, conversion from Set is slow
// for each item in the shortest array
for (let i = 0; i < shortest.length; i++) {
const item = shortest[i];
// see if item is in every subsequent array
let every = true; // don't use ordered.every ... it is slow
for (let j = 1; j < ordered.length; j++) {
if (ordered[j].includes(item)) continue;
every = false;
break;
}
// ignore if not in every other array, or if already captured
if (!every || set.has(item)) continue;
// otherwise, add to bookeeping set and the result
set.add(item);
result[result.length] = item;
}
return result;
};
export default class ObsidianAdmonition extends Plugin {
async onload(): Promise<void> {
console.log("Obsidian Admonition loaded");

this.registerMarkdownPostProcessor(this.postprocessor.bind(this));
}
postprocessor(el: HTMLElement, ctx: MarkdownPostProcessorContext) {
/* */
//don't process if no code elements in element;
let codeBlocks = el.querySelectorAll("code");
if (!codeBlocks.length) return;
const classMap = Object.keys(ADMONITION_MAP).map(
(k) => `language-${k}`
);

codeBlocks = Array.prototype.map
.call(
codeBlocks,
(element: HTMLElement): HTMLElement => {
if (element) {
const classList = Array.prototype.filter.call(
element.classList,
(cls: string) => classMap.includes(cls)
);
if (classList.length) return element;
}
}
)
.filter((b: HTMLElement) => b);
//don't process if the code block is not an admonition type
codeBlocks = Array.prototype.filter.call(
codeBlocks,
(element: HTMLElement) =>
element &&
fastIntersection(
Array.prototype.slice.call(element.classList),
classMap
).length > 0
);
if (!codeBlocks.length) return;

//render admonition element
codeBlocks.forEach((block) => {
if (block) {
let classType = Array.prototype.find.call(
block.classList,
(cls: string) => classMap.includes(cls)
);
if (!classType) return;
let type =
ADMONITION_MAP[classType.split("language-").pop().trim()];
if (!type) return;
ADMONITION_MAP[
Array.prototype.find
.call(block.classList, (cls: string) =>
classMap.includes(cls)
)
.split("language-")
.pop()
.trim()
];
if (!type) {
new Notice("There was an error rendering the admonition.");
return;
}
let params = Object.fromEntries(
block.innerText
.split("\n")
Expand All @@ -53,13 +117,6 @@ export default class Admonition extends Plugin {
content = block.innerText,
collapse
} = params;
console.log(
"🚀 ~ file: main.ts ~ line 56 ~ Admonition ~ codeBlocks.forEach ~ params",
params,
block.innerText
.split("\n")
.map((l) => l.split(":").map((s) => s.trim()))
);

if (
Object.prototype.hasOwnProperty.call(params, "title") &&
Expand All @@ -71,14 +128,12 @@ export default class Admonition extends Plugin {
if (
Object.prototype.hasOwnProperty.call(params, "collapse") &&
(params.collapse.length == 0 ||
params.collapse === undefined)
params.collapse === undefined ||
collapse !== "open")
) {
collapse = "closed";
}
console.log(
"🚀 ~ file: main.ts ~ line 69 ~ Admonition ~ codeBlocks.forEach ~ params.collapse",
collapse
);

this.buildAdmonition(
block.parentElement,
type,
Expand All @@ -97,15 +152,9 @@ export default class Admonition extends Plugin {
collapse?: string
) {
let attrs,
els = [
"div" as keyof HTMLElementTagNameMap,
"div" as keyof HTMLElementTagNameMap
];
if (collapse && ["open", "closed"].includes(collapse)) {
els = [
"details" as keyof HTMLElementTagNameMap,
"summary" as keyof HTMLElementTagNameMap
];
els: Array<keyof HTMLElementTagNameMap> = ["div", "div"];
if (collapse) {
els = ["details", "summary"];
attrs = {
[collapse]: true
};
Expand Down
2 changes: 1 addition & 1 deletion versions.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"0.0.5": "0.11.0"
"0.1.0": "0.11.0"
}

0 comments on commit f506641

Please sign in to comment.