Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions content/articles/my-blog/my-blog.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ I must give a lot of credit to [brandur](https://github.com/brandur/sorg) for cr

I totally just took that, and rolled with it

![](./brandur.png)
[![](./brandur.png)](https://brandur.org/)
*Brandur's lovely site*

I also did take great inspiration from [Victor Zhou's](https://victorzhou.com/) blog which looks very aesthetically pleasing and has tags ([yoinked](https://github.com/pjohnst5/CoolsterCodes/pull/32) that feature for myself)
I also did take great inspiration from Victor Zhou's blog which looks very aesthetically pleasing and has tags ([yoinked](https://github.com/pjohnst5/CoolsterCodes/pull/32) that feature for myself)

![](./Victor.png)
[![](./Victor.png)](https://victorzhou.com/)
*Victor's lovely site*

## Features
Expand Down
62 changes: 60 additions & 2 deletions modules/modulir/mmarkdownext/mmarkdownext.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func Render(s string, options *RenderOptions) (string, error) {
// to get our fully rendered Markdown. This includes the rendering itself, but
// also a number of custom transformation options.
var renderStack = []func(string, *RenderOptions) (string, error){
transformLinkedImages,
transformImages,
transformPDFs,
transformVideos,
Expand Down Expand Up @@ -117,6 +118,58 @@ func transformCaption(rawCaption string, opts *RenderOptions) string {
return captionAsHTML
}

const linkedImageHTMLCaption = `
<figure class="text-center">
<a href="%s"%s>
<img src="%s" />
</a>
<figcaption>%s</figcaption>
</figure>
`

const linkedImageHTMLNoCaption = `
<figure class="text-center">
<a href="%s"%s>
<img src="%s" />
</a>
</figure>
`

// linkedImageRE matches the pattern [![](./image.png)](https://google.com).
// with an optional caption on the next line: *some caption*
// Capture groups: 1=image path, 2=link URL, 3=full caption line (with newline and asterisks), 4=caption text only.
var linkedImageRE = regexp.MustCompile(`\[!\[\]\(([^)]+\.(?:png|jpg|jpeg|gif|svg))\)\]\(([^)]+)\)(\n\*(.*)\*)?`)

func transformLinkedImages(source string, opts *RenderOptions) (string, error) {
return linkedImageRE.ReplaceAllStringFunc(source, func(figure string) string {
matches := linkedImageRE.FindStringSubmatch(figure)
if len(matches) != 5 {
return figure
}
// Grab the image path
img := matches[1]
if opts.ImgDir != "" {
img = filepath.Join(opts.ImgDir, img)
}
// Grab the link URL
linkURL := matches[2]
// Determine target attribute based on link type (same logic as transformCaption)
targetAttr := ""
if strings.HasPrefix(linkURL, "http") {
targetAttr = ` target="_blank"`
}
// No caption option
if matches[3] == "" {
return fmt.Sprintf(linkedImageHTMLNoCaption, linkURL, targetAttr, img)
}
// Grab the caption
caption := matches[4]
// Process the caption in case it has markdown in it
htmlCaption := transformCaption(caption, opts)
return fmt.Sprintf(linkedImageHTMLCaption, linkURL, targetAttr, img, htmlCaption)
}), nil
}

const figureHTMLCaption = `
<figure class="text-center">
<a data-fancybox="gallery" href="%s" data-caption="%s">
Expand Down Expand Up @@ -761,10 +814,15 @@ func transformFootnotes(source string, _ *RenderOptions) (string, error) {
}

// This just always transforms any "http*" links to blank targets to open in new tabs.
var absoluteLinkRE = regexp.MustCompile(`<a href="http[^"]+"`)
var absoluteLinkRE = regexp.MustCompile(`<a[^>]*href="http[^"]*"[^>]*>`)

func transformLinksToTargetBlank(source string, _ *RenderOptions) (string, error) {
return absoluteLinkRE.ReplaceAllStringFunc(source, func(link string) string {
return link + " target=\"_blank\""
// Don't add target="_blank" if it already exists
if strings.Contains(link, `target="_blank"`) {
return link
}
// Insert target="_blank" before the closing >
return strings.TrimSuffix(link, ">") + ` target="_blank">`
}), nil
}
90 changes: 90 additions & 0 deletions modules/modulir/mmarkdownext/mmarkdownext_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,87 @@ func TestTransformImages(t *testing.T) {
)
}

func TestTransformLinkedImages(t *testing.T) {
assert.Equal(t, `
<figure class="text-center">
<a href="https://google.com" target="_blank">
<img src="/content/images/hey/image.png" />
</a>
<figcaption>some caption, but sometimes might not have a caption</figcaption>
</figure>
`,
must(transformLinkedImages(`[![](./image.png)](https://google.com)
*some caption, but sometimes might not have a caption*`, &RenderOptions{ImgDir: "/content/images/hey"})),
)

assert.Equal(t, `
<figure class="text-center">
<a href="https://google.com" target="_blank">
<img src="/content/images/hey/image.png" />
</a>
</figure>
`,
must(transformLinkedImages(`[![](./image.png)](https://google.com)`, &RenderOptions{ImgDir: "/content/images/hey"})),
)

// Test with relative link
assert.Equal(t, `
<figure class="text-center">
<a href="/some/page">
<img src="/content/images/hey/photo.jpg" />
</a>
<figcaption>A cool photo</figcaption>
</figure>
`,
must(transformLinkedImages(`[![](./photo.jpg)](/some/page)
*A cool photo*`, &RenderOptions{ImgDir: "/content/images/hey"})),
)

// Test with caption containing markdown
assert.Equal(t, `
<figure class="text-center">
<a href="https://example.com" target="_blank">
<img src="/content/images/hey/test.png" />
</a>
<figcaption>Check out this <a href="https://linked.com" target="_blank" class="text-myblue underline">cool link</a></figcaption>
</figure>
`,
must(transformLinkedImages(`[![](./test.png)](https://example.com)
*Check out this [cool link](https://linked.com)*`, &RenderOptions{ImgDir: "/content/images/hey"})),
)

// Test different image formats
assert.Equal(t, `
<figure class="text-center">
<a href="https://google.com" target="_blank">
<img src="/content/images/hey/image.jpeg" />
</a>
</figure>
`,
must(transformLinkedImages(`[![](./image.jpeg)](https://google.com)`, &RenderOptions{ImgDir: "/content/images/hey"})),
)

assert.Equal(t, `
<figure class="text-center">
<a href="https://google.com" target="_blank">
<img src="/content/images/hey/image.gif" />
</a>
</figure>
`,
must(transformLinkedImages(`[![](./image.gif)](https://google.com)`, &RenderOptions{ImgDir: "/content/images/hey"})),
)

assert.Equal(t, `
<figure class="text-center">
<a href="https://google.com" target="_blank">
<img src="/content/images/hey/image.svg" />
</a>
</figure>
`,
must(transformLinkedImages(`[![](./image.svg)](https://google.com)`, &RenderOptions{ImgDir: "/content/images/hey"})),
)
}

func TestTransformPDFs(t *testing.T) {
assert.Equal(t, `
<iframe width="100%" height="800" src="/content/images/hey/pdf.pdf">
Expand Down Expand Up @@ -263,6 +344,15 @@ func TestTransformLinksTargetBlank(t *testing.T) {
&RenderOptions{},
)),
)

// Links that already have target="_blank" should not get duplicated
assert.Equal(t,
`<a href="https://example.com" target="_blank">Example</a>`,
must(transformLinksToTargetBlank(
`<a href="https://example.com" target="_blank">Example</a>`,
&RenderOptions{},
)),
)
}

func must(v interface{}, err error) interface{} {
Expand Down