Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
caddy
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Łukasz Nowak
caddy
Commits
0bfdb50a
Commit
0bfdb50a
authored
May 07, 2015
by
Abiola Ibrahim
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
markdown: working version of template integration. Awaiting static site generation and tests.
parent
434ec7b6
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
124 additions
and
82 deletions
+124
-82
config/setup/markdown.go
config/setup/markdown.go
+21
-1
middleware/markdown/markdown.go
middleware/markdown/markdown.go
+7
-49
middleware/markdown/metadata.go
middleware/markdown/metadata.go
+7
-2
middleware/markdown/process.go
middleware/markdown/process.go
+89
-30
No files found.
config/setup/markdown.go
View file @
0bfdb50a
...
...
@@ -6,6 +6,7 @@ import (
"github.com/mholt/caddy/middleware"
"github.com/mholt/caddy/middleware/markdown"
"github.com/russross/blackfriday"
"path/filepath"
)
// Markdown configures a new Markdown middleware instance.
...
...
@@ -33,7 +34,9 @@ func markdownParse(c *Controller) ([]markdown.Config, error) {
for
c
.
Next
()
{
md
:=
markdown
.
Config
{
Renderer
:
blackfriday
.
HtmlRenderer
(
0
,
""
,
""
),
Renderer
:
blackfriday
.
HtmlRenderer
(
0
,
""
,
""
),
Templates
:
make
(
map
[
string
]
string
),
StaticFiles
:
make
(
map
[
string
]
string
),
}
// Get the path scope
...
...
@@ -61,6 +64,23 @@ func markdownParse(c *Controller) ([]markdown.Config, error) {
return
mdconfigs
,
c
.
ArgErr
()
}
md
.
Scripts
=
append
(
md
.
Scripts
,
c
.
Val
())
case
"template"
:
tArgs
:=
c
.
RemainingArgs
()
switch
len
(
tArgs
)
{
case
0
:
return
mdconfigs
,
c
.
ArgErr
()
case
1
:
if
_
,
ok
:=
md
.
Templates
[
markdown
.
DefaultTemplate
];
ok
{
return
mdconfigs
,
c
.
Err
(
"only one default template is allowed, use alias."
)
}
fpath
:=
filepath
.
Clean
(
c
.
Root
+
string
(
filepath
.
Separator
)
+
tArgs
[
0
])
md
.
Templates
[
markdown
.
DefaultTemplate
]
=
fpath
case
2
:
fpath
:=
filepath
.
Clean
(
c
.
Root
+
string
(
filepath
.
Separator
)
+
tArgs
[
1
])
md
.
Templates
[
tArgs
[
0
]]
=
fpath
default
:
return
mdconfigs
,
c
.
ArgErr
()
}
default
:
return
mdconfigs
,
c
.
Err
(
"Expected valid markdown configuration property"
)
}
...
...
middleware/markdown/markdown.go
View file @
0bfdb50a
...
...
@@ -3,11 +3,9 @@
package
markdown
import
(
"bytes"
"io/ioutil"
"net/http"
"os"
"path"
"strings"
"github.com/mholt/caddy/middleware"
...
...
@@ -51,7 +49,10 @@ type Config struct {
Scripts
[]
string
// Map of registered templates
Templates
map
[
string
]
string
Templates
map
[
string
]
string
// Static files
StaticFiles
map
[
string
]
string
}
// ServeHTTP implements the http.Handler interface.
...
...
@@ -81,37 +82,11 @@ func (md Markdown) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
return
http
.
StatusInternalServerError
,
err
}
content
:=
blackfriday
.
Markdown
(
body
,
m
.
Renderer
,
0
)
var
scripts
,
styles
string
for
_
,
style
:=
range
m
.
Styles
{
styles
+=
strings
.
Replace
(
cssTemplate
,
"{{url}}"
,
style
,
1
)
+
"
\r\n
"
}
for
_
,
script
:=
range
m
.
Scripts
{
scripts
+=
strings
.
Replace
(
jsTemplate
,
"{{url}}"
,
script
,
1
)
+
"
\r\n
"
}
// Title is first line (length-limited), otherwise filename
title
:=
path
.
Base
(
fpath
)
newline
:=
bytes
.
Index
(
body
,
[]
byte
(
"
\n
"
))
if
newline
>
-
1
{
firstline
:=
body
[
:
newline
]
newTitle
:=
strings
.
TrimSpace
(
string
(
firstline
))
if
len
(
newTitle
)
>
1
{
if
len
(
newTitle
)
>
128
{
title
=
newTitle
[
:
128
]
}
else
{
title
=
newTitle
}
}
html
,
err
:=
Process
(
md
,
fpath
,
body
)
if
err
!=
nil
{
return
http
.
StatusInternalServerError
,
err
}
html
:=
htmlTemplate
html
=
strings
.
Replace
(
html
,
"{{title}}"
,
title
,
1
)
html
=
strings
.
Replace
(
html
,
"{{css}}"
,
styles
,
1
)
html
=
strings
.
Replace
(
html
,
"{{js}}"
,
scripts
,
1
)
html
=
strings
.
Replace
(
html
,
"{{body}}"
,
string
(
content
),
1
)
w
.
Write
([]
byte
(
html
))
return
http
.
StatusOK
,
nil
...
...
@@ -122,20 +97,3 @@ func (md Markdown) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
// Didn't qualify to serve as markdown; pass-thru
return
md
.
Next
.
ServeHTTP
(
w
,
r
)
}
const
(
htmlTemplate
=
`<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
<meta charset="utf-8">
{{css}}
{{js}}
</head>
<body>
{{body}}
</body>
</html>`
cssTemplate
=
`<link rel="stylesheet" href="{{url}}">`
jsTemplate
=
`<script src="{{url}}"></script>`
)
middleware/markdown/metadata.go
View file @
0bfdb50a
...
...
@@ -17,12 +17,16 @@ var (
// Metadata stores a page's metadata
type
Metadata
struct
{
Title
string
Template
string
Variables
map
[
string
]
interface
{}
}
// Load loads parsed metadata into m
func
(
m
*
Metadata
)
load
(
parsedMap
map
[
string
]
interface
{})
{
if
template
,
ok
:=
parsedMap
[
"title"
];
ok
{
m
.
Title
,
_
=
template
.
(
string
)
}
if
template
,
ok
:=
parsedMap
[
"template"
];
ok
{
m
.
Template
,
_
=
template
.
(
string
)
}
...
...
@@ -37,6 +41,7 @@ type MetadataParser interface {
// Identifiers
Opening
()
[]
byte
Closing
()
[]
byte
Parse
([]
byte
)
error
Metadata
()
Metadata
}
...
...
@@ -121,12 +126,12 @@ func (y *YAMLMetadataParser) Metadata() Metadata {
return
y
.
metadata
}
// Opening returns the opening identifier
TO
ML metadata
// Opening returns the opening identifier
YA
ML metadata
func
(
y
*
YAMLMetadataParser
)
Opening
()
[]
byte
{
return
[]
byte
(
"---"
)
}
// Closing returns the closing identifier
TO
ML metadata
// Closing returns the closing identifier
YA
ML metadata
func
(
y
*
YAMLMetadataParser
)
Closing
()
[]
byte
{
return
[]
byte
(
"---"
)
}
middleware/markdown/process.go
View file @
0bfdb50a
...
...
@@ -5,41 +5,44 @@ import (
"bytes"
"fmt"
"io/ioutil"
"path/filepath"
"text/template"
"github.com/russross/blackfriday"
"strings"
)
// Process the contents of a page.
// It parses the metadata if any and uses the template if found
func
Process
(
c
Config
,
b
[]
byte
)
([]
byte
,
error
)
{
func
Process
(
c
Config
,
fpath
string
,
b
[]
byte
)
([]
byte
,
error
)
{
metadata
,
markdown
,
err
:=
extractMetadata
(
b
)
if
err
!=
nil
{
return
nil
,
err
}
// if metadata template is included
// if template is not specified, check if Default template is set
if
metadata
.
Template
==
""
{
if
_
,
ok
:=
c
.
Templates
[
DefaultTemplate
];
ok
{
metadata
.
Template
=
DefaultTemplate
}
}
// if template is set, load it
var
tmpl
[]
byte
if
metadata
.
Template
!=
""
{
if
t
,
ok
:=
c
.
Templates
[
metadata
.
Template
];
ok
{
tmpl
,
err
=
loadTemplat
e
(
t
)
tmpl
,
err
=
ioutil
.
ReadFil
e
(
t
)
}
if
err
!=
nil
{
return
nil
,
err
}
}
// if no template loaded
// use default template
if
tmpl
==
nil
{
tmpl
=
[]
byte
(
htmlTemplate
)
}
// process markdown
if
markdown
,
err
=
processMarkdown
(
markdown
,
metadata
.
Variables
);
err
!=
nil
{
return
nil
,
err
}
tmpl
=
bytes
.
Replace
(
tmpl
,
[]
byte
(
"{{body}}"
),
markdown
,
1
)
markdown
=
blackfriday
.
Markdown
(
markdown
,
c
.
Renderer
,
0
)
// set it as body for template
metadata
.
Variables
[
"body"
]
=
string
(
markdown
)
return
tmpl
,
nil
return
processTemplate
(
c
,
fpath
,
tmpl
,
metadata
)
}
// extractMetadata extracts metadata content from a page.
...
...
@@ -70,12 +73,22 @@ func extractMetadata(b []byte) (metadata Metadata, markdown []byte, err error) {
line
:=
scanner
.
Bytes
()
// closing identifier found
if
bytes
.
Equal
(
bytes
.
TrimSpace
(
line
),
parser
.
Closing
())
{
if
err
:=
parser
.
Parse
(
buf
.
Bytes
());
err
!=
nil
{
// parse the metadata
err
:=
parser
.
Parse
(
buf
.
Bytes
())
if
err
!=
nil
{
return
metadata
,
nil
,
err
}
return
parser
.
Metadata
(),
reader
.
Bytes
(),
nil
// get the scanner to return remaining bytes
scanner
.
Split
(
func
(
data
[]
byte
,
atEOF
bool
)
(
int
,
[]
byte
,
error
)
{
return
len
(
data
),
data
,
nil
})
// scan the remaining bytes
scanner
.
Scan
()
return
parser
.
Metadata
(),
scanner
.
Bytes
(),
nil
}
buf
.
Write
(
line
)
buf
.
WriteString
(
"
\r\n
"
)
}
return
metadata
,
nil
,
fmt
.
Errorf
(
"Metadata not closed. '%v' not found"
,
string
(
parser
.
Closing
()))
}
...
...
@@ -91,25 +104,71 @@ func findParser(line []byte) MetadataParser {
return
nil
}
func
loadTemplate
(
tmpl
string
)
([]
byte
,
error
)
{
b
,
err
:=
ioutil
.
ReadFile
(
tmpl
)
func
processTemplate
(
c
Config
,
fpath
string
,
tmpl
[]
byte
,
metadata
Metadata
)
([]
byte
,
error
)
{
// if template is specified
// replace parse the template
if
tmpl
!=
nil
{
tmpl
=
defaultTemplate
(
c
,
metadata
,
fpath
)
}
b
:=
&
bytes
.
Buffer
{}
t
,
err
:=
template
.
New
(
""
)
.
Parse
(
string
(
tmpl
))
if
err
!=
nil
{
return
nil
,
err
}
if
!
bytes
.
Contains
(
b
,
[]
byte
(
"{{body}}"
))
{
return
nil
,
fmt
.
Errorf
(
"template missing {{body}}"
)
if
err
=
t
.
Execute
(
b
,
metadata
.
Variables
);
err
!=
nil
{
return
nil
,
err
}
return
b
,
nil
return
b
.
Bytes
(),
nil
}
func
processMarkdown
(
b
[]
byte
,
vars
map
[
string
]
interface
{})
([]
byte
,
error
)
{
buf
:=
&
bytes
.
Buffer
{}
t
,
err
:=
template
.
New
(
"markdown"
)
.
Parse
(
string
(
b
))
if
err
!=
nil
{
return
nil
,
err
func
defaultTemplate
(
c
Config
,
metadata
Metadata
,
fpath
string
)
[]
byte
{
// else, use default template
var
scripts
,
styles
bytes
.
Buffer
for
_
,
style
:=
range
c
.
Styles
{
styles
.
WriteString
(
strings
.
Replace
(
cssTemplate
,
"{{url}}"
,
style
,
1
))
styles
.
WriteString
(
"
\r\n
"
)
}
if
err
:=
t
.
Execute
(
buf
,
vars
);
err
!=
nil
{
return
nil
,
err
for
_
,
script
:=
range
c
.
Scripts
{
scripts
.
WriteString
(
strings
.
Replace
(
jsTemplate
,
"{{url}}"
,
script
,
1
))
scripts
.
WriteString
(
"
\r\n
"
)
}
// Title is first line (length-limited), otherwise filename
title
:=
metadata
.
Title
if
title
==
""
{
title
=
filepath
.
Base
(
fpath
)
if
body
,
_
:=
metadata
.
Variables
[
"body"
]
.
([]
byte
);
len
(
body
)
>
128
{
title
=
string
(
body
[
:
128
])
}
else
if
len
(
body
)
>
0
{
title
=
string
(
body
)
}
}
return
buf
.
Bytes
(),
nil
html
:=
[]
byte
(
htmlTemplate
)
html
=
bytes
.
Replace
(
html
,
[]
byte
(
"{{title}}"
),
[]
byte
(
title
),
1
)
html
=
bytes
.
Replace
(
html
,
[]
byte
(
"{{css}}"
),
styles
.
Bytes
(),
1
)
html
=
bytes
.
Replace
(
html
,
[]
byte
(
"{{js}}"
),
scripts
.
Bytes
(),
1
)
return
html
}
const
(
htmlTemplate
=
`<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
<meta charset="utf-8">
{{css}}
{{js}}
</head>
<body>
{{.body}}
</body>
</html>`
cssTemplate
=
`<link rel="stylesheet" href="{{url}}">`
jsTemplate
=
`<script src="{{url}}"></script>`
DefaultTemplate
=
"defaultTemplate"
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment