feat: allow embedding youtube videos with the obsidian markdown syntax (#665)
* Add option to allow embedding YouTube videos with Obsidian Markdown syntax * Update Obsidian compatability doc page * Switch to converting YT links as an html plugin
This commit is contained in:
		@@ -26,6 +26,7 @@ Finally, Quartz also provides `Plugin.CrawlLinks` which allows you to customize
 | 
				
			|||||||
    - `mermaid`: whether to enable [[Mermaid diagrams]]. Defaults to `true`
 | 
					    - `mermaid`: whether to enable [[Mermaid diagrams]]. Defaults to `true`
 | 
				
			||||||
    - `parseTags`: whether to try and parse tags in the content body. Defaults to `true`
 | 
					    - `parseTags`: whether to try and parse tags in the content body. Defaults to `true`
 | 
				
			||||||
    - `enableInHtmlEmbed`: whether to try and parse Obsidian flavoured markdown in raw HTML. Defaults to `false`
 | 
					    - `enableInHtmlEmbed`: whether to try and parse Obsidian flavoured markdown in raw HTML. Defaults to `false`
 | 
				
			||||||
 | 
					    - `enableYouTubeEmbed`: whether to enable embedded YouTube videos using external image Markdown syntax. Defaults to `false`
 | 
				
			||||||
- Link resolution behaviour:
 | 
					- Link resolution behaviour:
 | 
				
			||||||
  - Disabling: remove all instances of `Plugin.CrawlLinks()` from `quartz.config.ts`
 | 
					  - Disabling: remove all instances of `Plugin.CrawlLinks()` from `quartz.config.ts`
 | 
				
			||||||
  - Changing link resolution preference: set `markdownLinkResolution` to one of `absolute`, `relative` or `shortest`
 | 
					  - Changing link resolution preference: set `markdownLinkResolution` to one of `absolute`, `relative` or `shortest`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,6 +25,7 @@ export interface Options {
 | 
				
			|||||||
  parseTags: boolean
 | 
					  parseTags: boolean
 | 
				
			||||||
  parseBlockReferences: boolean
 | 
					  parseBlockReferences: boolean
 | 
				
			||||||
  enableInHtmlEmbed: boolean
 | 
					  enableInHtmlEmbed: boolean
 | 
				
			||||||
 | 
					  enableYouTubeEmbed: boolean
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const defaultOptions: Options = {
 | 
					const defaultOptions: Options = {
 | 
				
			||||||
@@ -36,6 +37,7 @@ const defaultOptions: Options = {
 | 
				
			|||||||
  parseTags: true,
 | 
					  parseTags: true,
 | 
				
			||||||
  parseBlockReferences: true,
 | 
					  parseBlockReferences: true,
 | 
				
			||||||
  enableInHtmlEmbed: false,
 | 
					  enableInHtmlEmbed: false,
 | 
				
			||||||
 | 
					  enableYouTubeEmbed: false,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const icons = {
 | 
					const icons = {
 | 
				
			||||||
@@ -127,6 +129,7 @@ const calloutLineRegex = new RegExp(/^> *\[\!\w+\][+-]?.*$/, "gm")
 | 
				
			|||||||
// (?:\/[-_\p{L}\d\p{Z}]+)*)   -> non-capturing group, matches an arbitrary number of tag strings separated by "/"
 | 
					// (?:\/[-_\p{L}\d\p{Z}]+)*)   -> non-capturing group, matches an arbitrary number of tag strings separated by "/"
 | 
				
			||||||
const tagRegex = new RegExp(/(?:^| )#((?:[-_\p{L}\p{Emoji}\d])+(?:\/[-_\p{L}\p{Emoji}\d]+)*)/, "gu")
 | 
					const tagRegex = new RegExp(/(?:^| )#((?:[-_\p{L}\p{Emoji}\d])+(?:\/[-_\p{L}\p{Emoji}\d]+)*)/, "gu")
 | 
				
			||||||
const blockReferenceRegex = new RegExp(/\^([A-Za-z0-9]+)$/, "g")
 | 
					const blockReferenceRegex = new RegExp(/\^([A-Za-z0-9]+)$/, "g")
 | 
				
			||||||
 | 
					const ytLinkRegex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options> | undefined> = (
 | 
					export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options> | undefined> = (
 | 
				
			||||||
  userOpts,
 | 
					  userOpts,
 | 
				
			||||||
@@ -505,6 +508,30 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>
 | 
				
			|||||||
        })
 | 
					        })
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (opts.enableYouTubeEmbed) {
 | 
				
			||||||
 | 
					        plugins.push(() => {
 | 
				
			||||||
 | 
					          return (tree: HtmlRoot) => {
 | 
				
			||||||
 | 
					            visit(tree, "element", (node) => {
 | 
				
			||||||
 | 
					              if (node.tagName === "img" && typeof node.properties.src === "string") {
 | 
				
			||||||
 | 
					                const match = node.properties.src.match(ytLinkRegex)
 | 
				
			||||||
 | 
					                const videoId = match && match[2].length == 11 ? match[2] : null
 | 
				
			||||||
 | 
					                if (videoId) {
 | 
				
			||||||
 | 
					                  node.tagName = "iframe"
 | 
				
			||||||
 | 
					                  node.properties = {
 | 
				
			||||||
 | 
					                    class: "external-embed",
 | 
				
			||||||
 | 
					                    allow: "fullscreen",
 | 
				
			||||||
 | 
					                    frameborder: 0,
 | 
				
			||||||
 | 
					                    width: "600px",
 | 
				
			||||||
 | 
					                    height: "350px",
 | 
				
			||||||
 | 
					                    src: `https://www.youtube.com/embed/${videoId}`,
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return plugins
 | 
					      return plugins
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    externalResources() {
 | 
					    externalResources() {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user