Vivify icon indicating copy to clipboard operation
Vivify copied to clipboard

Obsidian style callouts

Open Tweekism opened this issue 1 year ago • 19 comments

As per https://github.com/iamcco/markdown-preview.nvim/discussions/682

Feature requested on iamcco plugin by 2 recent users.

OP @Praczet

Hi,

Firstly thank you for this plugin I really like it.

I would like to ask if it will be possible to add support for the Obsidian's callouts (markdown-it-obsidian-callouts)

Best regards

Tweekism avatar Jul 29 '24 01:07 Tweekism

Is this a full superset of GitHub alert blocks? I.e. if we ~~include this~~ replace the GitHub alert plugin with this, will the GitHub blocks still work?

EDIT: Ah, by the way, I think the person who replied to that discussion is on windows so Vivify is not (yet) applicable for them. The OP I haven't seen before, but I would wait until we hear from them here that they would want this here before adding it :)

jannis-baum avatar Jul 29 '24 05:07 jannis-baum

That's what I was looking at. How deep do you want to go implementing stuff like this, obsidian on its own is a whole massive rabbit hole.

Tweekism avatar Jul 29 '24 05:07 Tweekism

obsidian on its own is a whole massive rabbit hole.

Yep, exactly. That's why I would only do it if people ask for it explicitly. Also, I'm not familiar with Obsidian, but when I opened their page for a second it looked like a huge thing including the editor and viewer and all that so I don't know if people even have files from that laying around that they would want to look at in Vivify/edit in Vim

jannis-baum avatar Jul 29 '24 05:07 jannis-baum

Then lets close for now as not planned? and revisit if there's demand for it.

Tweekism avatar Jul 29 '24 05:07 Tweekism

Yes sounds good! We can reopen if @ Praczet stops by and/or someone else wants it as well.

jannis-baum avatar Jul 29 '24 05:07 jannis-baum

I'm also very interested, hopefully it will be implemented one day 🙂.

pidgeon777 avatar Aug 05 '24 08:08 pidgeon777

Also looking for this feature 👍

gaardhus avatar Aug 24 '24 20:08 gaardhus

Fair to say it's a popular request, reopening

But I have the same question as @jannis-baum above:

Is this similar to Github Style Alerts?

The biggest functional difference I can see is foldability

And another one is nestability, it apparently doesn't work with our github alert plugin, but I'd be interested in 'fixing' that.

i.e.:

image

Other than that it looks like something that could be achieved through theming the github alerts.

tuurep avatar Aug 24 '24 21:08 tuurep

Oh hold on, there's mention about Obsidian callout syntax support in the Github alert plugin's readme:

https://github.com/antfu/markdown-it-github-alerts?tab=readme-ov-file#customization

In order to also support Obsidian callouts syntax it is possible to allow any type of markers with the following setting:

md.use(MarkdownItGitHubAlerts, {
 markers: '*'
})

So.. if we simply enable that, how much would that solve?

tuurep avatar Aug 24 '24 21:08 tuurep

Oh hold on, there's mention about Obsidian callout syntax support in the Github alert plugin's readme:

https://github.com/antfu/markdown-it-github-alerts?tab=readme-ov-file#customization

In order to also support Obsidian callouts syntax it is possible to allow any type of markers with the following setting:

md.use(MarkdownItGitHubAlerts, {
 markers: '*'
})

So.. if we simply enable that, how much would that solve?

If no one specifies what exactly they are looking for maybe let's just do this, make a release and then see if anyone complains?🙈

jannis-baum avatar Aug 26 '24 16:08 jannis-baum

So hmm I'm not quite sure how useful this is:

> [!note]
> hi

> [!info]
> jajdjdj

image

So it allows to give any id like > [!id] and then gives us a wholly unstyled <div class="markdown-alert markdown-alert-id">

First thing I notice is we need a generic styling for alert of any 'id'

So it would be easy to allow to customize any arbitrary alert type, but with a bit of effort because a custom icon would need to be provided too.

Also note that this is already possible:

> [!important] foo
> abc

> [!caution] bar
> def

> [!note] baz
> ghi

> [!warning] qux
> jkl

> [!tip] xyzzy
> mno

image

But again info for people who request this: we aren't familiar with Obsidian usage and currently may have a severe lack of understanding what the expectation is here :)

tuurep avatar Aug 26 '24 17:08 tuurep

Hi, Finally I (ok we) managed to force my Manjaro to work with vivify-server and as I kind of started this discussion I will tell you what I wanted:

  1. That preview is rendering callouts at all - which here is done.
  2. Other type? I am using quite often:
    • question
    • quote
    • todo
    • example
  3. Nested callouts- I don't need, but it could be ok to have it
  4. Folding - personally - I don't need

When I was looking today in your source code to check why my question-callout is not rendered I noticed that you use markdown-it-github-alert. The md.use

md.use(MarkdownItGitHubAlerts, {
 markers: '*'
})

would work if in neovim you could in config (setup) add styling something like this:

  { "jannis-baum/vivify.vim" 
    config = function()
      require("vivify").setup({
        "markdown-alerts = {
            "question" = {
                 css={},
                  icon ={},
                 -- etc
             }
        }
   })
   end,
  },

But this is what I would like to have, since I am using vivify-server only with neovim.

Did I thank you for a help with vivify-server and implementing the github alerts? If not: thank you.

Praczet avatar Aug 31 '24 08:08 Praczet

Hey thanks for the input

Ok so as far as I understand the main thing would be to be able to use any custom [!foo] and then have the associated, user-configured style and icon

It would be probably better to do the user customization on main Vivify's side so it will work both for standalone viv and also any future editors someone might wanna plug into Vivify

So makes me wonder if it's enough to set the markers: '*' and then you can customize any arbitrary keyword for example [!foo]

~/.vivify/config.json

{
  "styles": "~/.vivify/styles.css"
}

~/.vivify/styles.css

.markdown-alert-foo {
  /* Set any CSS you want */
}

^ This is generally what I'd suggest at this point, there's a couple more details:

  • Where do the svg icons come from
  • Might want to set some kinda sensible default style for .markdown-alert-* (I've got an idea)

If you've got some objections to this approach due to me missing something, let us know :smile:

@jannis-baum What do you think?

tuurep avatar Aug 31 '24 13:08 tuurep

Also I might take a closer look at the markdown-it plugin markdown-it-obsidian-callouts that you mentioned in the original discussion, if that gives some ideas as well

tuurep avatar Aug 31 '24 13:08 tuurep

Hi, I like this idea with configuration in vivify-server...

And about icons you could use icons from https://lucide.dev/ I think.

When I am exporting MD file to PDF. I am using fancyicon. for a callouts icons.

image

It goes thru LaTeX and filters like this:


% Success Callout
\newtcolorbox{callout-success}{
  colback=calloutBackground, % Dark background for the content area
  colframe=calloutSuccess, % Green left border and title color
  fonttitle=\bfseries, % Title font color same as pageFontColor
  coltitle=calloutSuccess, % Title color matching the left border
  colbacktitle=calloutBackground, % Title background matches the content area
  coltext=pageFontColor,
  boxrule=0.5mm, % Thin border
  arc=4mm, % Rounded corners
  leftrule=2mm, rightrule=0mm, toprule=0mm, bottomrule=0mm, % Only left border
  left=2mm, right=2mm, top=2mm, bottom=2mm, % Padding inside the box
  before skip=10pt, after skip=10pt, % Vertical space before and after the box
  sharp corners, % Optional: to have sharp inner corners
  titlerule=0mm, % No title underline or border
  title=\faCheck\ Success, % Title with icon
}

and lua script:

function BlockQuote(el)
	local first = el.content[1]

	if first and first.t == "Para" then
		local text = pandoc.utils.stringify(first.content[1])
		local callout_type = text:match("%[!(%u+)%]")

		if callout_type then
			-- Remove the callout marker from the text
			el.content[1].content[1].text = first.content[1].text:gsub("%[!%u+%]%s*", "")

			-- Define the callout styles
			local blocks = pandoc.List()

			if FORMAT:match("html") then
				local icon_html = ""
				if callout_type == "NOTE" then
					icon_html = "&#xf05a;" -- info-circle
				elseif callout_type == "TIP" then
					icon_html = "&#xf0eb;" -- lightbulb
				elseif callout_type == "IMPORTANT" then
					icon_html = "&#xf071;" -- exclamation-triangle
				elseif callout_type == "WARNING" then
					icon_html = "&#xf06a;" -- exclamation-circle
				elseif callout_type == "CAUTION" then
					icon_html = "&#xf071;" -- exclamation-triangle
				elseif callout_type == "ABSTRACT" then
					icon_html = "&#xf02d;" -- book
				elseif callout_type == "TODO" then
					icon_html = "&#xf046;" -- check-square
				elseif callout_type == "SUCCESS" then
					icon_html = "&#xf00c;" -- check
				elseif callout_type == "QUESTION" then
					icon_html = "&#xf059;" -- question-circle
				elseif callout_type == "FAILURE" then
					icon_html = "&#xf057;" -- times-circle
				elseif callout_type == "DANGER" then
					icon_html = "&#xf1e2;" -- bomb
				elseif callout_type == "BUG" then
					icon_html = "&#xf188;" -- bug
				elseif callout_type == "EXAMPLE" then
					icon_html = "&#xf121;" -- code
				elseif callout_type == "QUOTE" then
					icon_html = "&#xf10d;" -- quote-left
				end

				local start_html = string.format(
					'<div class="callout callout-%s"><strong>%s %s</strong>',
					callout_type:lower(),
					icon_html,
					callout_type
				)
				blocks:insert(pandoc.RawBlock("html", start_html))
				blocks:extend(el.content)
				blocks:insert(pandoc.RawBlock("html", "</div>"))
				return blocks
			elseif FORMAT:match("latex") then
				-- Map callout types to LaTeX tcolorbox environments
				local env_name = "callout-" .. callout_type:lower()
				local start_latex = string.format("\\begin{%s}", env_name)
				blocks:insert(pandoc.RawBlock("latex", start_latex))
				blocks:extend(el.content)
				blocks:insert(pandoc.RawBlock("latex", "\\end{" .. env_name .. "}"))
				return blocks
			end
		end
	end
end

return {
	{ BlockQuote = BlockQuote },
}

Praczet avatar Aug 31 '24 18:08 Praczet

@jannis-baum What do you think?

@tuurep sounds good what you said! The configuration should definitely happen on main Vivify as you said, editor plugin config only makes sense for things specific to the editor. This is viewer-topic.

About the icons, I would strongly prefer to avoid introducing a second source of icons. The Octicons probably have something suitable. If not, I'd rather switch to whatever new source for everything instead of having two.

In case the icons need to be accessible from CSS, we could consider symlinking the Octicon SVGs from the Node plugin into our static assets to compile them into the executable the way I recently did it for KaTeX and Mermaid. Just have to keep an eye on how much bigger this makes the executable, but I'd guess it'll be fine

jannis-baum avatar Aug 31 '24 18:08 jannis-baum

In case the icons need to be accessible from CSS

Yeah as I imagine it right now, they'd need to be

Note that also what we were talking about here https://github.com/jannis-baum/Vivify/pull/162#issuecomment-2295317109 is always possible by either inlining the whole svg or putting it as a file in your configs or something

I definitely have enough to start making a PR in the not too distant future, but think I need help with this part:

we could consider symlinking the Octicon SVGs from the Node plugin into our static assets to compile them into the executable the way I recently did it for KaTeX and Mermaid.

:)

tuurep avatar Aug 31 '24 19:08 tuurep

Note that also what we were talking about here #162 (comment) is always possible by either inlining the whole svg or putting it as a file in your configs or something

Yes, true, I had already forgotten about this again haha. This is a great option for custom configs. For Vivify itself I think we should always try to go for the symlinking approach so that things keep themselves up to date and we don't have manual copies laying around. I'll help with that :)

jannis-baum avatar Sep 01 '24 16:09 jannis-baum

Returning to this issue/draft PR lately!

In case the icons need to be accessible from CSS

Yeah as I imagine it right now, they'd need to be

We had a change of plan about this, CSS is not a good place to add/specify the SVG icons so this will most likely be configured in config.json, similar to for example the toc plugin.

The idea is to give the options as seen here:

https://github.com/antfu/markdown-it-github-alerts/blob/23d2d84c738e206b74762e388ca35c076d170028/src/index.ts#L3-L38

.. in config.json. Then based on the config, they're set here:

https://github.com/jannis-baum/Vivify/blob/0e10b2ecf78376b4157d74901e8ed79e511c8906/src/parser/markdown.ts#L69

^ mdit.use(githubAlerts, config.alertsOptions) <-- TODO

Edit: we ended up rewriting markdown-it-github-alerts for our purposes.

tuurep avatar Oct 24 '24 18:10 tuurep

@Praczet @pidgeon777 @gaardhus @luposmi

Big news for everyone requesting this feature, it's in!

Here are some examples on how to use custom alerts:

Minimal configs to create all distinct alert types from the Obsidian default ones using our system:

config.json (icons):

{
    "styles": "styles.css",

    "alertOptions": {
        "icons": {
            "info": "info",
            "note": "pencil",
            "todo": "check-circle",
            "tip": "flame",
            "abstract": "project-roadmap",
            "success": "check",
            "question": "question",
            "failure": "x",
            "danger": "zap",
            "bug": "bug",
            "example": "list-unordered"
        }
    }
}

styles.css (colors):

.alert-info     { --color: var(--alert-note); }
.alert-todo     { --color: var(--alert-note); }
.alert-tip      { --color: #06909e; }
.alert-abstract { --color: #06909e; }
.alert-example  { --color: var(--alert-important); }
.alert-question { --color: var(--alert-warning); }
.alert-success  { --color: var(--alert-tip); }
.alert-failure  { --color: var(--alert-caution); }
.alert-danger   { --color: var(--alert-caution); }
.alert-bug      { --color: var(--alert-caution); }

Would result in this:

Image

Or you can create completely custom types, like:

{
    "styles": "styles.css",

    "alertOptions": {
        "icons": {
            "fix": "tools",
            "comment": "comment",
            "theory": "book"
        }
    }
}
.alert-fix     { --color: var(--alert-tip); }
.alert-comment { --color: #b63163; }
.alert-theory  { --color: #133992; }
Image

For a full explanation on alerts, see the docs.

For a complete example to use all of Obsidian's default alert types, including the aliases, see this discussion.

See octicons for the most easy to use icons for custom alerts, but note that you can possibly use other icons too: advanced icon configuration

tuurep avatar Sep 08 '25 18:09 tuurep