From e0bc4260506f18895f7cc4916cd8ee0e0f32f482 Mon Sep 17 00:00:00 2001 From: Tobias Weingartner Date: Sat, 30 Apr 2016 17:01:31 -0700 Subject: [PATCH] Initial re-add of markdown summary functionality. --- middleware/markdown/metadata/metadata.go | 4 - middleware/markdown/process.go | 39 ++++++- middleware/markdown/summary/render.go | 143 +++++++++++++++++++++++ middleware/markdown/summary/summary.go | 16 +++ middleware/markdown/template.go | 7 +- 5 files changed, 196 insertions(+), 13 deletions(-) create mode 100644 middleware/markdown/summary/render.go create mode 100644 middleware/markdown/summary/summary.go diff --git a/middleware/markdown/metadata/metadata.go b/middleware/markdown/metadata/metadata.go index a861ee4e..ade7fcc9 100644 --- a/middleware/markdown/metadata/metadata.go +++ b/middleware/markdown/metadata/metadata.go @@ -3,7 +3,6 @@ package metadata import ( "bufio" "bytes" - "os" "time" ) @@ -32,9 +31,6 @@ type Metadata struct { // Flags to be used with Template Flags map[string]bool - - // Directory entries present, if a directory - Dirents []os.FileInfo } // NewMetadata() returns a new Metadata struct, loaded with the given map diff --git a/middleware/markdown/process.go b/middleware/markdown/process.go index bae5cf81..15e5e7ca 100644 --- a/middleware/markdown/process.go +++ b/middleware/markdown/process.go @@ -1,14 +1,36 @@ package markdown import ( + "io/ioutil" "os" "path/filepath" "github.com/mholt/caddy/middleware" "github.com/mholt/caddy/middleware/markdown/metadata" + "github.com/mholt/caddy/middleware/markdown/summary" "github.com/russross/blackfriday" ) +type FileInfo struct { + os.FileInfo + ctx middleware.Context +} + +func (f FileInfo) Summarize(wordcount int) string { + fp, err := f.ctx.Root.Open(f.Name()) + if err != nil { + return "" + } + defer fp.Close() + + buf, err := ioutil.ReadAll(fp) + if err != nil { + return "" + } + + return string(summary.Markdown(buf, wordcount)) +} + // Markdown processes the contents of a page in b. It parses the metadata // (if any) and uses the template (if found). func (c *Config) Markdown(requestPath string, b []byte, dirents []os.FileInfo, ctx middleware.Context) ([]byte, error) { @@ -26,6 +48,8 @@ func (c *Config) Markdown(requestPath string, b []byte, dirents []os.FileInfo, c // set it as body for template mdata.Variables["body"] = string(markdown) + + // fixup title title := mdata.Title if title == "" { title = filepath.Base(requestPath) @@ -34,12 +58,15 @@ func (c *Config) Markdown(requestPath string, b []byte, dirents []os.FileInfo, c } mdata.Variables["title"] = title - if len(dirents) > 0 { - mdata.Flags["dirents"] = true - mdata.Dirents = dirents - } else { - mdata.Flags["dirents"] = false + // massage possible files + files := []FileInfo{} + for _, ent := range dirents { + file := FileInfo{ + FileInfo: ent, + ctx: ctx, + } + files = append(files, file) } - return execTemplate(c, mdata, ctx) + return execTemplate(c, mdata, files, ctx) } diff --git a/middleware/markdown/summary/render.go b/middleware/markdown/summary/render.go new file mode 100644 index 00000000..fb11841c --- /dev/null +++ b/middleware/markdown/summary/render.go @@ -0,0 +1,143 @@ +package summary + +import ( + "bytes" + + "github.com/russross/blackfriday" +) + +// Ensure we implement the Blackfriday Markdown Renderer interface +var _ blackfriday.Renderer = (*Renderer)(nil) + +type Renderer struct{} + +// Blocklevel callbacks + +// BlockCode is the code tag callback. +func (r Renderer) BlockCode(out *bytes.Buffer, text []byte, land string) {} + +// BlockQuote is teh quote tag callback. +func (r Renderer) BlockQuote(out *bytes.Buffer, text []byte) {} + +// BlockHtml is the HTML tag callback. +func (r Renderer) BlockHtml(out *bytes.Buffer, text []byte) {} + +// Header is the header tag callback. +func (r Renderer) Header(out *bytes.Buffer, text func() bool, level int, id string) {} + +// HRule is the horizontal rule tag callback. +func (r Renderer) HRule(out *bytes.Buffer) {} + +// List is the list tag callback. +func (r Renderer) List(out *bytes.Buffer, text func() bool, flags int) { + // TODO: This is not desired (we'd rather not write lists as part of summary), + // but see this issue: https://github.com/russross/blackfriday/issues/189 + marker := out.Len() + if !text() { + out.Truncate(marker) + } + out.Write([]byte{' '}) +} + +// ListItem is the list item tag callback. +func (r Renderer) ListItem(out *bytes.Buffer, text []byte, flags int) {} + +// Paragraph is the paragraph tag callback. +func (r Renderer) Paragraph(out *bytes.Buffer, text func() bool) { + marker := out.Len() + if !text() { + out.Truncate(marker) + } + out.Write([]byte{' '}) +} + +// Table is the table tag callback. +func (r Renderer) Table(out *bytes.Buffer, header []byte, body []byte, columnData []int) {} + +// TableRow is the table row tag callback. +func (r Renderer) TableRow(out *bytes.Buffer, text []byte) {} + +// TableHeaderCell is the table header cell tag callback. +func (r Renderer) TableHeaderCell(out *bytes.Buffer, text []byte, flags int) {} + +// TableCell is the table cell tag callback. +func (r Renderer) TableCell(out *bytes.Buffer, text []byte, flags int) {} + +// Footnotes is the foot notes tag callback. +func (r Renderer) Footnotes(out *bytes.Buffer, text func() bool) {} + +// FootnoteItem is the footnote item tag callback. +func (r Renderer) FootnoteItem(out *bytes.Buffer, name, text []byte, flags int) {} + +// TitleBlock is the title tag callback. +func (r Renderer) TitleBlock(out *bytes.Buffer, text []byte) {} + +// Spanlevel callbacks + +// AutoLink is the autolink tag callback. +func (r Renderer) AutoLink(out *bytes.Buffer, link []byte, kind int) {} + +// CodeSpan is the code span tag callback. +func (r Renderer) CodeSpan(out *bytes.Buffer, text []byte) { + out.Write([]byte("`")) + out.Write(text) + out.Write([]byte("`")) +} + +// DoubleEmphasis is the double emphasis tag callback. +func (r Renderer) DoubleEmphasis(out *bytes.Buffer, text []byte) { + out.Write(text) +} + +// Emphasis is the emphasis tag callback. +func (r Renderer) Emphasis(out *bytes.Buffer, text []byte) { + out.Write(text) +} + +// Image is the image tag callback. +func (r Renderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {} + +// LineBreak is the line break tag callback. +func (r Renderer) LineBreak(out *bytes.Buffer) {} + +// Link is the link tag callback. +func (r Renderer) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) { + out.Write(content) +} + +// RawHtmlTag is the raw HTML tag callback. +func (r Renderer) RawHtmlTag(out *bytes.Buffer, tag []byte) {} + +// TripleEmphasis is the triple emphasis tag callback. +func (r Renderer) TripleEmphasis(out *bytes.Buffer, text []byte) { + out.Write(text) +} + +// StrikeThrough is the strikethrough tag callback. +func (r Renderer) StrikeThrough(out *bytes.Buffer, text []byte) {} + +// FootnoteRef is the footnote ref tag callback. +func (r Renderer) FootnoteRef(out *bytes.Buffer, ref []byte, id int) {} + +// Lowlevel callbacks + +// Entity callback. +func (r Renderer) Entity(out *bytes.Buffer, entity []byte) { + out.Write(entity) +} + +// NormalText callback. +func (r Renderer) NormalText(out *bytes.Buffer, text []byte) { + out.Write(text) +} + +// Header and footer + +// DocumentHeader callback. +func (r Renderer) DocumentHeader(out *bytes.Buffer) {} + +// DocumentFooter callback. +func (r Renderer) DocumentFooter(out *bytes.Buffer) {} + +// GetFlags returns zero. +func (r Renderer) GetFlags() int { return 0 } diff --git a/middleware/markdown/summary/summary.go b/middleware/markdown/summary/summary.go new file mode 100644 index 00000000..2527de03 --- /dev/null +++ b/middleware/markdown/summary/summary.go @@ -0,0 +1,16 @@ +package summary + +import ( + "bytes" + + "github.com/russross/blackfriday" +) + +func Markdown(input []byte, wordcount int) []byte { + words := bytes.Fields(blackfriday.Markdown(input, Renderer{}, 0)) + if wordcount > len(words) { + wordcount = len(words) + } + + return bytes.Join(words[0:wordcount], []byte{' '}) +} diff --git a/middleware/markdown/template.go b/middleware/markdown/template.go index f9f1f661..76d3a99d 100644 --- a/middleware/markdown/template.go +++ b/middleware/markdown/template.go @@ -3,7 +3,7 @@ package markdown import ( "bytes" "io/ioutil" - "os" + // "os" "text/template" "github.com/mholt/caddy/middleware" @@ -17,7 +17,7 @@ type Data struct { DocFlags map[string]bool Styles []string Scripts []string - Files []os.FileInfo + Files []FileInfo } // Include "overrides" the embedded middleware.Context's Include() @@ -28,13 +28,14 @@ func (d Data) Include(filename string) (string, error) { } // execTemplate executes a template given a requestPath, template, and metadata -func execTemplate(c *Config, mdata metadata.Metadata, ctx middleware.Context) ([]byte, error) { +func execTemplate(c *Config, mdata metadata.Metadata, files []FileInfo, ctx middleware.Context) ([]byte, error) { mdData := Data{ Context: ctx, Doc: mdata.Variables, DocFlags: mdata.Flags, Styles: c.Styles, Scripts: c.Scripts, + Files: files, } b := new(bytes.Buffer)