From cc5acdff194eb43ef5a9d80f4829f28cec143040 Mon Sep 17 00:00:00 2001 From: valentine195 <38669521+valentine195@users.noreply.github.com> Date: Mon, 3 May 2021 15:33:35 -0400 Subject: [PATCH] 4.0.0 - Nested admonitions now possible (closes #16 ) --- @types/types.ts | 6 +++ README.md | 40 +++++++++++++++---- images/nested.PNG | Bin 0 -> 9783 bytes manifest.json | 2 +- package.json | 2 +- src/main.ts | 96 ++++++++++++++++++++-------------------------- src/util.ts | 81 +++++++++++++++++++++++++++++++++++++- versions.json | 3 +- 8 files changed, 165 insertions(+), 65 deletions(-) create mode 100644 images/nested.PNG diff --git a/@types/types.ts b/@types/types.ts index 5e14b9c..9e2f06d 100644 --- a/@types/types.ts +++ b/@types/types.ts @@ -6,6 +6,12 @@ export interface Admonition { color: string; } +export interface INestedAdmonition { + type: string; + start: number; + end: number; + src: string; +} export declare class ObsidianAdmonitionPlugin extends Plugin_2 { removeAdmonition: (admonition: Admonition) => Promise; admonitions: { [admonitionType: string]: Admonition }; diff --git a/README.md b/README.md index 5e575b9..962984c 100644 --- a/README.md +++ b/README.md @@ -32,12 +32,6 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. ``` ```` -### Content - -Content is the actual text of the admonition. - -**Note: As of 0.2.0, this is no longer required. Anything other than `title:` and `collapse:` will be included as the content.** - ### Titles The admonition will render with the type of admonition by default. If you wish to customize the title, you can do so this way: @@ -77,6 +71,35 @@ If a blank title is provided, the collapse parameter will not do anything. ![](https://raw.githubusercontent.com/valentine195/obsidian-admonition/master/images/collapse.gif) +## Nesting Admonitions + +Admonitions may be nested inside each other indefinitely using the [Python Markdown](https://python-markdown.github.io/extensions/admonition/) syntax. + +> :warning: **Please note that this syntax _cannot_ be used for the original admonition. It must be a codeblock (```).** + +Example: + +```` +```ad-note +title: Nested Admonitions +collapse: open + +Hello! + +!!! ad-note + title: This admonition is nested. + This is a nested admonition! + !!! ad-warning + title: This admonition is closed. + collapse: close + + +This is in the original admonition. +``` +```` + +![](https://raw.githubusercontent.com/valentine195/obsidian-admonition/master/images/nested.gif) + ## Admonition Types The following admonition types are currently supported: @@ -260,13 +283,16 @@ An icon without a title will have this CSS: # Version History +## 4.0.0 + +- Nested admonitions are now possible + ## 3.3.0 - Added commands to open and collapse all admonitions in active note - Admonition icons now respect the font size of the admonition title - Collapse handle now centers inside the title element - CSS changes -- ## 3.2.0 diff --git a/images/nested.PNG b/images/nested.PNG new file mode 100644 index 0000000000000000000000000000000000000000..a78f02aefa84101cafd1875d2e2a97e457c40ac7 GIT binary patch literal 9783 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 OICb3iSn+R&=>Gtv(8H|& literal 0 HcmV?d00001 diff --git a/manifest.json b/manifest.json index 892f019..a5a867c 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "obsidian-admonition", "name": "Admonition", - "version": "3.3.4", + "version": "4.0.0", "minAppVersion": "0.11.0", "description": "Admonition block-styled content for Obsidian.md", "author": "Jeremy Valentine", diff --git a/package.json b/package.json index 897c97e..88ea281 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsidian-admonition", - "version": "3.3.4", + "version": "4.0.0", "description": "Admonition block-styled content for Obsidian.md", "main": "main.js", "scripts": { diff --git a/src/main.ts b/src/main.ts index 579168e..49b73f6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,8 +6,16 @@ import { Notice, Plugin } from "obsidian"; -import { Admonition, ObsidianAdmonitionPlugin } from "../@types/types"; -import { getAdmonitionElement } from "./util"; +import { + Admonition, + INestedAdmonition, + ObsidianAdmonitionPlugin +} from "../@types/types"; +import { + getAdmonitionElement, + getMatches, + getParametersFromSource +} from "./util"; import * as CodeMirror from "./codemirror"; @@ -100,6 +108,9 @@ export default class ObsidianAdmonition admonitions: { [admonitionType: string]: Admonition } = {}; userAdmonitions: { [admonitionType: string]: Admonition } = {}; syntaxHighlight: boolean; + get types() { + return Object.keys(this.admonitions); + } async saveSettings() { await this.saveData({ syntaxHighlight: this.syntaxHighlight || false, @@ -260,63 +271,40 @@ export default class ObsidianAdmonition return; } try { - /** - * Find title and collapse parameters. - */ - let matchedParameters = - src.match(/^\b(title|collapse)\b:([\s\S]*?)$/gm) || []; - - let params = Object.fromEntries( - matchedParameters.map((p) => { - let [, param, rest] = p.match( - /^\b(title|collapse)\b:([\s\S]*?)$/ - ); - return [param.trim(), rest.trim()]; - }) - ); - let { title = type[0].toUpperCase() + type.slice(1).toLowerCase(), - collapse - } = params; + collapse, + content + } = getParametersFromSource(type, src); + + let match = new RegExp(`^!!! ad-(${this.types.join("|")})$`, "gm"); + + let nestedAdmonitions = content.match(match) || []; + + if (nestedAdmonitions.length) { + let matches = [getMatches(content, 0, nestedAdmonitions[0])]; + for (let i = 1; i < nestedAdmonitions.length; i++) { + matches.push( + getMatches( + content, + matches[i - 1].end, + nestedAdmonitions[i] + ) + ); + } - /** - * Get the content. Content should be everything that is not the title or collapse parameters. - * Remove any "content: " fields (legacy from < v0.2.0) - */ - let content = src - .replace(/^\b(title|collapse)\b:([\s\S]*?)$/gm, "") - .replace(/^\bcontent\b:\s?/gm, ""); - /** - * If the admonition should collapse, but something other than open or closed was provided, set to closed. - */ - if ( - Object.prototype.hasOwnProperty.call(params, "collapse") && - (params.collapse.length == 0 || - params.collapse === undefined || - collapse !== "open") - ) { - collapse = "closed"; - } - /** - * If the admonition should collapse, but title was blanked, set the default title. - */ - if ( - Object.prototype.hasOwnProperty.call(params, "title") && - (params.title === undefined || params.title.length === 0) && - collapse - ) { - title = type[0].toUpperCase() + type.slice(1).toLowerCase(); - new Notice( - "An admonition must have a title if it is collapsible." - ); + let split = content.split("\n"); + + for (let m of matches.reverse()) { + split.splice( + m.start, + m.end - m.start + 1, + `\`\`\`ad-${m.type}\n${m.src}\n\`\`\`` + ); + } + content = split.join("\n"); } - /** - * Build the correct admonition element. - * Collapsible ->
Title
Content
- * Regular ->
Title
Content
- */ let admonitionElement = getAdmonitionElement( type, title, diff --git a/src/util.ts b/src/util.ts index 930da9f..fb1c0f7 100644 --- a/src/util.ts +++ b/src/util.ts @@ -3,7 +3,86 @@ import { icon, IconName } from "@fortawesome/fontawesome-svg-core"; -import { MarkdownRenderer } from "obsidian"; +import { INestedAdmonition } from "../@types/types"; +import { MarkdownRenderer, Notice } from "obsidian"; + +export function getMatches( + src: string, + from: number, + toMatch: string +): INestedAdmonition { + const split = src.split("\n").slice(from); + const first = split.indexOf(split.find((l) => l == toMatch)); + + let next = first + 1; + for (; next < split.length; next++) { + if (!/^(?: {2,4}|\t)+[\s\S]*?/.test(split[next])) break; + } + + let innerSrc = split.slice(first + 1, next).join("\n"); + + const toRemove = innerSrc.split("\n")[0].match(/^(\s+)/); + innerSrc = innerSrc.replace(new RegExp(`^${toRemove[0] || ""}`, "gm"), ""); + + return { + start: first + from, + end: next + from - 1, + src: innerSrc, + type: toMatch.split("-").pop() + }; +} + +export function getParametersFromSource(type: string, src: string) { + /** + * Find title and collapse parameters. + */ + let matchedParameters = + src.match(/^\b(title|collapse)\b:([\s\S]*?)$/gm) || []; + + let params = Object.fromEntries( + matchedParameters.map((p) => { + let [, param, rest] = p.match(/^\b(title|collapse)\b:([\s\S]*?)$/); + return [param.trim(), rest.trim()]; + }) + ); + + let { + title = type[0].toUpperCase() + type.slice(1).toLowerCase(), + collapse + } = params; + + /** + * Get the content. Content should be everything that is not the title or collapse parameters. + * Remove any "content: " fields (legacy from < v0.2.0) + */ + let content = src + .replace(/^\b(title|collapse)\b:([\s\S]*?)$/gm, "") + .replace(/^\bcontent\b:\s?/gm, ""); + /** + * If the admonition should collapse, but something other than open or closed was provided, set to closed. + */ + if ( + Object.prototype.hasOwnProperty.call(params, "collapse") && + (params.collapse.length == 0 || + params.collapse === undefined || + collapse !== "open") + ) { + collapse = "closed"; + } + /** + * If the admonition should collapse, but title was blanked, set the default title. + */ + if ( + Object.prototype.hasOwnProperty.call(params, "title") && + (params.title === undefined || params.title.length === 0) && + collapse + ) { + title = type[0].toUpperCase() + type.slice(1).toLowerCase(); + new Notice("An admonition must have a title if it is collapsible."); + } + + return { title, collapse, content }; +} export /* async */ function getAdmonitionElement( type: string, diff --git a/versions.json b/versions.json index 60dbd14..1627b7d 100644 --- a/versions.json +++ b/versions.json @@ -4,5 +4,6 @@ "2.0.1": "0.11.0", "3.1.2": "0.11.0", "3.2.2": "0.11.0", - "3.3.4": "0.11.0" + "3.3.4": "0.11.0", + "4.0.0": "0.11.0" } \ No newline at end of file