mirror of
https://github.com/caddyserver/caddy.git
synced 2025-01-24 09:37:03 +01:00
Initial re-add of markdown summary functionality.
This commit is contained in:
parent
bd2a33dd14
commit
e0bc426050
5 changed files with 196 additions and 13 deletions
|
@ -3,7 +3,6 @@ package metadata
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,9 +31,6 @@ type Metadata struct {
|
||||||
|
|
||||||
// Flags to be used with Template
|
// Flags to be used with Template
|
||||||
Flags map[string]bool
|
Flags map[string]bool
|
||||||
|
|
||||||
// Directory entries present, if a directory
|
|
||||||
Dirents []os.FileInfo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMetadata() returns a new Metadata struct, loaded with the given map
|
// NewMetadata() returns a new Metadata struct, loaded with the given map
|
||||||
|
|
|
@ -1,14 +1,36 @@
|
||||||
package markdown
|
package markdown
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/mholt/caddy/middleware"
|
"github.com/mholt/caddy/middleware"
|
||||||
"github.com/mholt/caddy/middleware/markdown/metadata"
|
"github.com/mholt/caddy/middleware/markdown/metadata"
|
||||||
|
"github.com/mholt/caddy/middleware/markdown/summary"
|
||||||
"github.com/russross/blackfriday"
|
"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
|
// Markdown processes the contents of a page in b. It parses the metadata
|
||||||
// (if any) and uses the template (if found).
|
// (if any) and uses the template (if found).
|
||||||
func (c *Config) Markdown(requestPath string, b []byte, dirents []os.FileInfo, ctx middleware.Context) ([]byte, error) {
|
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
|
// set it as body for template
|
||||||
mdata.Variables["body"] = string(markdown)
|
mdata.Variables["body"] = string(markdown)
|
||||||
|
|
||||||
|
// fixup title
|
||||||
title := mdata.Title
|
title := mdata.Title
|
||||||
if title == "" {
|
if title == "" {
|
||||||
title = filepath.Base(requestPath)
|
title = filepath.Base(requestPath)
|
||||||
|
@ -34,12 +58,15 @@ func (c *Config) Markdown(requestPath string, b []byte, dirents []os.FileInfo, c
|
||||||
}
|
}
|
||||||
mdata.Variables["title"] = title
|
mdata.Variables["title"] = title
|
||||||
|
|
||||||
if len(dirents) > 0 {
|
// massage possible files
|
||||||
mdata.Flags["dirents"] = true
|
files := []FileInfo{}
|
||||||
mdata.Dirents = dirents
|
for _, ent := range dirents {
|
||||||
} else {
|
file := FileInfo{
|
||||||
mdata.Flags["dirents"] = false
|
FileInfo: ent,
|
||||||
|
ctx: ctx,
|
||||||
|
}
|
||||||
|
files = append(files, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
return execTemplate(c, mdata, ctx)
|
return execTemplate(c, mdata, files, ctx)
|
||||||
}
|
}
|
||||||
|
|
143
middleware/markdown/summary/render.go
Normal file
143
middleware/markdown/summary/render.go
Normal file
|
@ -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 }
|
16
middleware/markdown/summary/summary.go
Normal file
16
middleware/markdown/summary/summary.go
Normal file
|
@ -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{' '})
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ package markdown
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
// "os"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/mholt/caddy/middleware"
|
"github.com/mholt/caddy/middleware"
|
||||||
|
@ -17,7 +17,7 @@ type Data struct {
|
||||||
DocFlags map[string]bool
|
DocFlags map[string]bool
|
||||||
Styles []string
|
Styles []string
|
||||||
Scripts []string
|
Scripts []string
|
||||||
Files []os.FileInfo
|
Files []FileInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include "overrides" the embedded middleware.Context's Include()
|
// 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
|
// 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{
|
mdData := Data{
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
Doc: mdata.Variables,
|
Doc: mdata.Variables,
|
||||||
DocFlags: mdata.Flags,
|
DocFlags: mdata.Flags,
|
||||||
Styles: c.Styles,
|
Styles: c.Styles,
|
||||||
Scripts: c.Scripts,
|
Scripts: c.Scripts,
|
||||||
|
Files: files,
|
||||||
}
|
}
|
||||||
|
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
|
|
Loading…
Reference in a new issue