mirror of
				https://github.com/kovetskiy/mark.git
				synced 2025-11-04 06:17:36 +08:00 
			
		
		
		
	Support inline images
This commit is contained in:
		
							parent
							
								
									2b756daf37
								
							
						
					
					
						commit
						fd97ee70f9
					
				
							
								
								
									
										14
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								README.md
									
									
									
									
									
								
							@ -300,8 +300,8 @@ By default, mark provides several built-in templates and macros:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
* template: `ac:youtube` to include YouTube Widget. Parameters:
 | 
					* template: `ac:youtube` to include YouTube Widget. Parameters:
 | 
				
			||||||
  - URL: YouTube video endpoint
 | 
					  - URL: YouTube video endpoint
 | 
				
			||||||
  - Width: Width in px. Defualts to "640px"
 | 
					  - Width: Width in px. Defaults to "640px"
 | 
				
			||||||
  - Height: Height in px. Defualts to "360px"
 | 
					  - Height: Height in px. Defaults to "360px"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  See: https://confluence.atlassian.com/doc/widget-connector-macro-171180449.html#WidgetConnectorMacro-YouTube
 | 
					  See: https://confluence.atlassian.com/doc/widget-connector-macro-171180449.html#WidgetConnectorMacro-YouTube
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -537,6 +537,15 @@ And this is how to link when the linktext is the same as the [Pagetitle](ac:)
 | 
				
			|||||||
Link to a [page title with space](<ac:With Space>)
 | 
					Link to a [page title with space](<ac:With Space>)
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Upload and included inline images
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```markdown
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					will automatically upload the inlined image as an attachment and inline the image using the `ac:image` template.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If the file is not found, it will inline the image using the `ac:image` template and link to the image.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Add width for an image
 | 
					### Add width for an image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Use the following macro:
 | 
					Use the following macro:
 | 
				
			||||||
@ -552,6 +561,7 @@ And attach any image with the following
 | 
				
			|||||||
```
 | 
					```
 | 
				
			||||||
The width will be the commented html after the image (in this case 300px).
 | 
					The width will be the commented html after the image (in this case 300px).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Currently this is not compatible with the automated upload of inline images.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Render Mermaid Diagram
 | 
					### Render Mermaid Diagram
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								main.go
									
									
									
									
									
								
							@ -364,7 +364,7 @@ func processFile(
 | 
				
			|||||||
			markdown = mark.DropDocumentLeadingH1(markdown)
 | 
								markdown = mark.DropDocumentLeadingH1(markdown)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		html, _ := mark.CompileMarkdown(markdown, stdlib, cCtx.String("mermaid-provider"))
 | 
							html, _ := mark.CompileMarkdown(markdown, stdlib, file, cCtx.String("mermaid-provider"))
 | 
				
			||||||
		fmt.Println(html)
 | 
							fmt.Println(html)
 | 
				
			||||||
		os.Exit(0)
 | 
							os.Exit(0)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -441,7 +441,7 @@ func processFile(
 | 
				
			|||||||
		markdown = mark.DropDocumentLeadingH1(markdown)
 | 
							markdown = mark.DropDocumentLeadingH1(markdown)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	html, inlineAttachments := mark.CompileMarkdown(markdown, stdlib, cCtx.String("mermaid-provider"))
 | 
						html, inlineAttachments := mark.CompileMarkdown(markdown, stdlib, file, cCtx.String("mermaid-provider"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Resolve attachements detected from markdown
 | 
						// Resolve attachements detected from markdown
 | 
				
			||||||
	_, err = mark.ResolveAttachments(
 | 
						_, err = mark.ResolveAttachments(
 | 
				
			||||||
 | 
				
			|||||||
@ -166,7 +166,8 @@ func SubstituteLinks(markdown []byte, links []LinkSubstitution) []byte {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func parseLinks(markdown string) []markdownLink {
 | 
					func parseLinks(markdown string) []markdownLink {
 | 
				
			||||||
	re := regexp.MustCompile(`\[[^\]]+\]\((([^\)#]+)?#?([^\)]+)?)\)`)
 | 
						// Matches links but not inline images
 | 
				
			||||||
 | 
						re := regexp.MustCompile(`[^\!]\[[^\]]+\]\((([^\)#]+)?#?([^\)]+)?)\)`)
 | 
				
			||||||
	matches := re.FindAllStringSubmatch(markdown, -1)
 | 
						matches := re.FindAllStringSubmatch(markdown, -1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	links := make([]markdownLink, len(matches))
 | 
						links := make([]markdownLink, len(matches))
 | 
				
			||||||
 | 
				
			|||||||
@ -3,11 +3,13 @@ package mark
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
	"regexp"
 | 
						"regexp"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cparser "github.com/kovetskiy/mark/pkg/mark/parser"
 | 
						cparser "github.com/kovetskiy/mark/pkg/mark/parser"
 | 
				
			||||||
	"github.com/kovetskiy/mark/pkg/mark/stdlib"
 | 
						"github.com/kovetskiy/mark/pkg/mark/stdlib"
 | 
				
			||||||
 | 
						"github.com/kovetskiy/mark/pkg/mark/vfs"
 | 
				
			||||||
	"github.com/reconquest/pkg/log"
 | 
						"github.com/reconquest/pkg/log"
 | 
				
			||||||
	"github.com/yuin/goldmark"
 | 
						"github.com/yuin/goldmark"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -49,16 +51,18 @@ func (m BlockQuoteLevelMap) Level(node ast.Node) int {
 | 
				
			|||||||
type ConfluenceRenderer struct {
 | 
					type ConfluenceRenderer struct {
 | 
				
			||||||
	html.Config
 | 
						html.Config
 | 
				
			||||||
	Stdlib          *stdlib.Lib
 | 
						Stdlib          *stdlib.Lib
 | 
				
			||||||
 | 
						Path            string
 | 
				
			||||||
	MermaidProvider string
 | 
						MermaidProvider string
 | 
				
			||||||
	LevelMap        BlockQuoteLevelMap
 | 
						LevelMap        BlockQuoteLevelMap
 | 
				
			||||||
	Attachments     []Attachment
 | 
						Attachments     []Attachment
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewConfluenceRenderer creates a new instance of the ConfluenceRenderer
 | 
					// NewConfluenceRenderer creates a new instance of the ConfluenceRenderer
 | 
				
			||||||
func NewConfluenceRenderer(stdlib *stdlib.Lib, mermaidProvider string, opts ...html.Option) renderer.NodeRenderer {
 | 
					func NewConfluenceRenderer(stdlib *stdlib.Lib, path string, mermaidProvider string, opts ...html.Option) renderer.NodeRenderer {
 | 
				
			||||||
	return &ConfluenceRenderer{
 | 
						return &ConfluenceRenderer{
 | 
				
			||||||
		Config:          html.NewConfig(),
 | 
							Config:          html.NewConfig(),
 | 
				
			||||||
		Stdlib:          stdlib,
 | 
							Stdlib:          stdlib,
 | 
				
			||||||
 | 
							Path:            path,
 | 
				
			||||||
		MermaidProvider: mermaidProvider,
 | 
							MermaidProvider: mermaidProvider,
 | 
				
			||||||
		LevelMap:        nil,
 | 
							LevelMap:        nil,
 | 
				
			||||||
		Attachments:     []Attachment{},
 | 
							Attachments:     []Attachment{},
 | 
				
			||||||
@ -84,7 +88,7 @@ func (r *ConfluenceRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegister
 | 
				
			|||||||
	// reg.Register(ast.KindAutoLink, r.renderNode)
 | 
						// reg.Register(ast.KindAutoLink, r.renderNode)
 | 
				
			||||||
	// reg.Register(ast.KindCodeSpan, r.renderNode)
 | 
						// reg.Register(ast.KindCodeSpan, r.renderNode)
 | 
				
			||||||
	// reg.Register(ast.KindEmphasis, r.renderNode)
 | 
						// reg.Register(ast.KindEmphasis, r.renderNode)
 | 
				
			||||||
	// reg.Register(ast.KindImage, r.renderNode)
 | 
						reg.Register(ast.KindImage, r.renderImage)
 | 
				
			||||||
	reg.Register(ast.KindLink, r.renderLink)
 | 
						reg.Register(ast.KindLink, r.renderLink)
 | 
				
			||||||
	// reg.Register(ast.KindRawHTML, r.renderNode)
 | 
						// reg.Register(ast.KindRawHTML, r.renderNode)
 | 
				
			||||||
	// reg.Register(ast.KindText, r.renderNode)
 | 
						// reg.Register(ast.KindText, r.renderNode)
 | 
				
			||||||
@ -372,11 +376,13 @@ func (r *ConfluenceRenderer) renderFencedCodeBlock(writer util.BufWriter, source
 | 
				
			|||||||
				Width      string
 | 
									Width      string
 | 
				
			||||||
				Height     string
 | 
									Height     string
 | 
				
			||||||
				Title      string
 | 
									Title      string
 | 
				
			||||||
 | 
									Alt        string
 | 
				
			||||||
				Attachment string
 | 
									Attachment string
 | 
				
			||||||
			}{
 | 
								}{
 | 
				
			||||||
				attachment.Width,
 | 
									attachment.Width,
 | 
				
			||||||
				attachment.Height,
 | 
									attachment.Height,
 | 
				
			||||||
				attachment.Name,
 | 
									attachment.Name,
 | 
				
			||||||
 | 
									"",
 | 
				
			||||||
				attachment.Filename,
 | 
									attachment.Filename,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
@ -463,10 +469,72 @@ func (r *ConfluenceRenderer) renderCodeBlock(writer util.BufWriter, source []byt
 | 
				
			|||||||
	return ast.WalkContinue, nil
 | 
						return ast.WalkContinue, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func CompileMarkdown(markdown []byte, stdlib *stdlib.Lib, mermaidProvider string) (string, []Attachment) {
 | 
					// renderImage renders an inline image
 | 
				
			||||||
 | 
					func (r *ConfluenceRenderer) renderImage(writer util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
 | 
				
			||||||
 | 
						if !entering {
 | 
				
			||||||
 | 
							return ast.WalkContinue, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						n := node.(*ast.Image)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						attachments, err := ResolveLocalAttachments(vfs.LocalOS, filepath.Dir(r.Path), []string{string(n.Destination)})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We were unable to resolve it locally, treat as URL
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							err = r.Stdlib.Templates.ExecuteTemplate(
 | 
				
			||||||
 | 
								writer,
 | 
				
			||||||
 | 
								"ac:image",
 | 
				
			||||||
 | 
								struct {
 | 
				
			||||||
 | 
									Width      string
 | 
				
			||||||
 | 
									Height     string
 | 
				
			||||||
 | 
									Title      string
 | 
				
			||||||
 | 
									Alt        string
 | 
				
			||||||
 | 
									Attachment string
 | 
				
			||||||
 | 
									Url        string
 | 
				
			||||||
 | 
								}{
 | 
				
			||||||
 | 
									"",
 | 
				
			||||||
 | 
									"",
 | 
				
			||||||
 | 
									string(n.Title),
 | 
				
			||||||
 | 
									string(nodeToHTMLText(n, source)),
 | 
				
			||||||
 | 
									"",
 | 
				
			||||||
 | 
									string(n.Destination),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							r.Attachments = append(r.Attachments, attachments[0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err = r.Stdlib.Templates.ExecuteTemplate(
 | 
				
			||||||
 | 
								writer,
 | 
				
			||||||
 | 
								"ac:image",
 | 
				
			||||||
 | 
								struct {
 | 
				
			||||||
 | 
									Width      string
 | 
				
			||||||
 | 
									Height     string
 | 
				
			||||||
 | 
									Title      string
 | 
				
			||||||
 | 
									Alt        string
 | 
				
			||||||
 | 
									Attachment string
 | 
				
			||||||
 | 
									Url        string
 | 
				
			||||||
 | 
								}{
 | 
				
			||||||
 | 
									"",
 | 
				
			||||||
 | 
									"",
 | 
				
			||||||
 | 
									string(n.Title),
 | 
				
			||||||
 | 
									string(nodeToHTMLText(n, source)),
 | 
				
			||||||
 | 
									attachments[0].Filename,
 | 
				
			||||||
 | 
									"",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return ast.WalkStop, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ast.WalkSkipChildren, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func CompileMarkdown(markdown []byte, stdlib *stdlib.Lib, path string, mermaidProvider string) (string, []Attachment) {
 | 
				
			||||||
	log.Tracef(nil, "rendering markdown:\n%s", string(markdown))
 | 
						log.Tracef(nil, "rendering markdown:\n%s", string(markdown))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	confluenceRenderer := NewConfluenceRenderer(stdlib, mermaidProvider)
 | 
						confluenceRenderer := NewConfluenceRenderer(stdlib, path, mermaidProvider)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	converter := goldmark.New(
 | 
						converter := goldmark.New(
 | 
				
			||||||
		goldmark.WithExtensions(
 | 
							goldmark.WithExtensions(
 | 
				
			||||||
@ -530,3 +598,18 @@ func ExtractDocumentLeadingH1(markdown []byte) string {
 | 
				
			|||||||
		return string(groups[1])
 | 
							return string(groups[1])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// https://github.com/yuin/goldmark/blob/c446c414ef3a41fb562da0ae5badd18f1502c42f/renderer/html/html.go
 | 
				
			||||||
 | 
					func nodeToHTMLText(n ast.Node, source []byte) []byte {
 | 
				
			||||||
 | 
						var buf bytes.Buffer
 | 
				
			||||||
 | 
						for c := n.FirstChild(); c != nil; c = c.NextSibling() {
 | 
				
			||||||
 | 
							if s, ok := c.(*ast.String); ok && s.IsCode() {
 | 
				
			||||||
 | 
								buf.Write(s.Text(source))
 | 
				
			||||||
 | 
							} else if !c.HasChildren() {
 | 
				
			||||||
 | 
								buf.Write(util.EscapeHTML(c.Text(source)))
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								buf.Write(nodeToHTMLText(c, source))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return buf.Bytes()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -36,7 +36,7 @@ func TestCompileMarkdown(t *testing.T) {
 | 
				
			|||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			panic(err)
 | 
								panic(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		actual, _ := CompileMarkdown(markdown, lib, "")
 | 
							actual, _ := CompileMarkdown(markdown, lib, filename, "")
 | 
				
			||||||
		test.EqualValues(string(html), actual, filename+" vs "+htmlname)
 | 
							test.EqualValues(string(html), actual, filename+" vs "+htmlname)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -201,7 +201,7 @@ func templates(api *confluence.API) (*template.Template, error) {
 | 
				
			|||||||
			`{{ if .Page}}`,
 | 
								`{{ if .Page}}`,
 | 
				
			||||||
			/**/ `<ac:parameter ac:name="page">`,
 | 
								/**/ `<ac:parameter ac:name="page">`,
 | 
				
			||||||
			/**/ `<ac:link>`,
 | 
								/**/ `<ac:link>`,
 | 
				
			||||||
			/**/ `<ri:page ri:content-title="{{ .Page}}"/>`,
 | 
								/**/ `<ri:page ri:content-title="{{ .Page }}"/>`,
 | 
				
			||||||
			/**/ `</ac:link>`,
 | 
								/**/ `</ac:link>`,
 | 
				
			||||||
			/**/ `</ac:parameter>`,
 | 
								/**/ `</ac:parameter>`,
 | 
				
			||||||
			`{{printf "\n"}}{{end}}`,
 | 
								`{{printf "\n"}}{{end}}`,
 | 
				
			||||||
@ -217,10 +217,16 @@ func templates(api *confluence.API) (*template.Template, error) {
 | 
				
			|||||||
		`ac:emoticon`: text(
 | 
							`ac:emoticon`: text(
 | 
				
			||||||
			`<ac:emoticon ac:name="{{ .Name }}"/>`,
 | 
								`<ac:emoticon ac:name="{{ .Name }}"/>`,
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		`ac:image`: text(
 | 
							`ac:image`: text(
 | 
				
			||||||
			`<ac:image{{ if .Width}} ac:width="{{ .Width }}"{{end}}{{ if .Height }} ac:height="{{ .Height }}"{{end}}{{ if .Title }} ac:title="{{ .Title }}"{{end}}>{{printf "\n"}}`,
 | 
								`<ac:image`,
 | 
				
			||||||
			`<ri:attachment ri:filename="{{ .Attachment | convertAttachment }}"/>{{printf "\n"}}`,
 | 
								`{{ if .Width }} ac:width="{{ .Width }}"{{end}}`,
 | 
				
			||||||
			`</ac:image>{{printf "\n"}}`,
 | 
								`{{ if .Height }} ac:height="{{ .Height }}"{{end}}`,
 | 
				
			||||||
 | 
								`{{ if .Title }} ac:title="{{ .Title }}"{{end}}`,
 | 
				
			||||||
 | 
								`{{ if .Alt }} ac:alt="{{ .Alt }}"{{end}}>`,
 | 
				
			||||||
 | 
								`{{ if .Attachment }}<ri:attachment ri:filename="{{ .Attachment | convertAttachment }}"/>{{end}}`,
 | 
				
			||||||
 | 
								`{{ if .Url }}<ri:url ri:value="{{ .Url }}"/>{{end}}`,
 | 
				
			||||||
 | 
								`</ac:image>`,
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* https://confluence.atlassian.com/doc/widget-connector-macro-171180449.html#WidgetConnectorMacro-YouTube */
 | 
							/* https://confluence.atlassian.com/doc/widget-connector-macro-171180449.html#WidgetConnectorMacro-YouTube */
 | 
				
			||||||
@ -240,9 +246,9 @@ func templates(api *confluence.API) (*template.Template, error) {
 | 
				
			|||||||
		`ac:iframe`: text(
 | 
							`ac:iframe`: text(
 | 
				
			||||||
			`<ac:structured-macro ac:name="iframe">{{printf "\n"}}`,
 | 
								`<ac:structured-macro ac:name="iframe">{{printf "\n"}}`,
 | 
				
			||||||
			`<ac:parameter ac:name="src"><ri:url ri:value="{{ .URL }}" /></ac:parameter>{{printf "\n"}}`,
 | 
								`<ac:parameter ac:name="src"><ri:url ri:value="{{ .URL }}" /></ac:parameter>{{printf "\n"}}`,
 | 
				
			||||||
			`{{ if .Frameborder}}<ac:parameter ac:name="frameborder">{{ .Frameborder }}</ac:parameter>{{printf "\n"}}{{end}}`,
 | 
								`{{ if .Frameborder }}<ac:parameter ac:name="frameborder">{{ .Frameborder }}</ac:parameter>{{printf "\n"}}{{end}}`,
 | 
				
			||||||
			`{{ if .Scrolling}}<ac:parameter ac:name="id">{{ .Scrolling }}</ac:parameter>{{printf "\n"}}{{end}}`,
 | 
								`{{ if .Scrolling }}<ac:parameter ac:name="id">{{ .Scrolling }}</ac:parameter>{{printf "\n"}}{{end}}`,
 | 
				
			||||||
			`{{ if .Align}}<ac:parameter ac:name="align">{{ .Align }}</ac:parameter>{{printf "\n"}}{{end}}`,
 | 
								`{{ if .Align }}<ac:parameter ac:name="align">{{ .Align }}</ac:parameter>{{printf "\n"}}{{end}}`,
 | 
				
			||||||
			`<ac:parameter ac:name="width">{{ or .Width "640px" }}</ac:parameter>{{printf "\n"}}`,
 | 
								`<ac:parameter ac:name="width">{{ or .Width "640px" }}</ac:parameter>{{printf "\n"}}`,
 | 
				
			||||||
			`<ac:parameter ac:name="height">{{ or .Height "360px" }}</ac:parameter>{{printf "\n"}}`,
 | 
								`<ac:parameter ac:name="height">{{ or .Height "360px" }}</ac:parameter>{{printf "\n"}}`,
 | 
				
			||||||
			`</ac:structured-macro>{{printf "\n"}}`,
 | 
								`</ac:structured-macro>{{printf "\n"}}`,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								pkg/mark/testdata/links.html
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								pkg/mark/testdata/links.html
									
									
									
									
										vendored
									
									
								
							@ -4,6 +4,8 @@
 | 
				
			|||||||
<p>Use <ac:link><ri:page ri:content-title="AnotherPage"/><ac:plain-text-link-body><![CDATA[AnotherPage]]></ac:plain-text-link-body></ac:link></p>
 | 
					<p>Use <ac:link><ri:page ri:content-title="AnotherPage"/><ac:plain-text-link-body><![CDATA[AnotherPage]]></ac:plain-text-link-body></ac:link></p>
 | 
				
			||||||
<p>Use <ac:link><ri:page ri:content-title="Another Page"/><ac:plain-text-link-body><![CDATA[Another Page]]></ac:plain-text-link-body></ac:link></p>
 | 
					<p>Use <ac:link><ri:page ri:content-title="Another Page"/><ac:plain-text-link-body><![CDATA[Another Page]]></ac:plain-text-link-body></ac:link></p>
 | 
				
			||||||
<p>Use <ac:link><ri:page ri:content-title="Page With Space"/><ac:plain-text-link-body><![CDATA[page link with spaces]]></ac:plain-text-link-body></ac:link></p>
 | 
					<p>Use <ac:link><ri:page ri:content-title="Page With Space"/><ac:plain-text-link-body><![CDATA[page link with spaces]]></ac:plain-text-link-body></ac:link></p>
 | 
				
			||||||
 | 
					<p><ac:image ac:alt="My Image"><ri:attachment ri:filename="test.png"/></ac:image></p>
 | 
				
			||||||
 | 
					<p><ac:image ac:alt="My External Image"><ri:url ri:value="http://confluence.atlassian.com/images/logo/confluence_48_trans.png"/></ac:image></p>
 | 
				
			||||||
<p>Use footnotes link <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
 | 
					<p>Use footnotes link <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
 | 
				
			||||||
<div class="footnotes" role="doc-endnotes">
 | 
					<div class="footnotes" role="doc-endnotes">
 | 
				
			||||||
<hr />
 | 
					<hr />
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										7
									
								
								pkg/mark/testdata/links.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								pkg/mark/testdata/links.md
									
									
									
									
										vendored
									
									
								
							@ -10,5 +10,10 @@ Use [Another Page](ac:)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Use [page link with spaces](<ac:Page With Space>)
 | 
					Use [page link with spaces](<ac:Page With Space>)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Use footnotes link [^1]  
 | 
					Use footnotes link [^1]  
 | 
				
			||||||
[^1]: a footnote link
 | 
					[^1]: a footnote link
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								pkg/mark/testdata/test.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								pkg/mark/testdata/test.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 3.9 KiB  | 
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user