summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/russross/blackfriday
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/russross/blackfriday')
-rw-r--r--vendor/github.com/russross/blackfriday/.gitignore8
-rw-r--r--vendor/github.com/russross/blackfriday/.travis.yml30
-rw-r--r--vendor/github.com/russross/blackfriday/README.md363
-rw-r--r--vendor/github.com/russross/blackfriday/block.go28
-rw-r--r--vendor/github.com/russross/blackfriday/doc.go32
-rw-r--r--vendor/github.com/russross/blackfriday/html.go3
-rw-r--r--vendor/github.com/russross/blackfriday/inline.go8
-rw-r--r--vendor/github.com/russross/blackfriday/markdown.go13
-rw-r--r--vendor/github.com/russross/blackfriday/smartypants.go58
9 files changed, 519 insertions, 24 deletions
diff --git a/vendor/github.com/russross/blackfriday/.gitignore b/vendor/github.com/russross/blackfriday/.gitignore
new file mode 100644
index 00000000..75623dcc
--- /dev/null
+++ b/vendor/github.com/russross/blackfriday/.gitignore
@@ -0,0 +1,8 @@
+*.out
+*.swp
+*.8
+*.6
+_obj
+_test*
+markdown
+tags
diff --git a/vendor/github.com/russross/blackfriday/.travis.yml b/vendor/github.com/russross/blackfriday/.travis.yml
new file mode 100644
index 00000000..a1687f17
--- /dev/null
+++ b/vendor/github.com/russross/blackfriday/.travis.yml
@@ -0,0 +1,30 @@
+sudo: false
+language: go
+go:
+ - 1.5.4
+ - 1.6.2
+ - tip
+matrix:
+ include:
+ - go: 1.2.2
+ script:
+ - go get -t -v ./...
+ - go test -v -race ./...
+ - go: 1.3.3
+ script:
+ - go get -t -v ./...
+ - go test -v -race ./...
+ - go: 1.4.3
+ script:
+ - go get -t -v ./...
+ - go test -v -race ./...
+ allow_failures:
+ - go: tip
+ fast_finish: true
+install:
+ - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step).
+script:
+ - go get -t -v ./...
+ - diff -u <(echo -n) <(gofmt -d -s .)
+ - go tool vet .
+ - go test -v -race ./...
diff --git a/vendor/github.com/russross/blackfriday/README.md b/vendor/github.com/russross/blackfriday/README.md
new file mode 100644
index 00000000..a6c94b79
--- /dev/null
+++ b/vendor/github.com/russross/blackfriday/README.md
@@ -0,0 +1,363 @@
+Blackfriday
+[![Build Status][BuildSVG]][BuildURL]
+[![Godoc][GodocV2SVG]][GodocV2URL]
+===========
+
+Blackfriday is a [Markdown][1] processor implemented in [Go][2]. It
+is paranoid about its input (so you can safely feed it user-supplied
+data), it is fast, it supports common extensions (tables, smart
+punctuation substitutions, etc.), and it is safe for all utf-8
+(unicode) input.
+
+HTML output is currently supported, along with Smartypants
+extensions.
+
+It started as a translation from C of [Sundown][3].
+
+
+Installation
+------------
+
+Blackfriday is compatible with any modern Go release. With Go and git installed:
+
+ go get -u gopkg.in/russross/blackfriday.v2
+
+will download, compile, and install the package into your `$GOPATH` directory
+hierarchy.
+
+
+Versions
+--------
+
+Currently maintained and recommended version of Blackfriday is `v2`. It's being
+developed on its own branch: https://github.com/russross/blackfriday/tree/v2 and the
+documentation is available at
+https://godoc.org/gopkg.in/russross/blackfriday.v2.
+
+It is `go get`-able via via [gopkg.in][6] at `gopkg.in/russross/blackfriday.v2`,
+but we highly recommend using package management tool like [dep][7] or
+[Glide][8] and make use of semantic versioning. With package management you
+should import `github.com/russross/blackfriday` and specify that you're using
+version 2.0.0.
+
+Version 2 offers a number of improvements over v1:
+
+* Cleaned up API
+* A separate call to [`Parse`][4], which produces an abstract syntax tree for
+ the document
+* Latest bug fixes
+* Flexibility to easily add your own rendering extensions
+
+Potential drawbacks:
+
+* Our benchmarks show v2 to be slightly slower than v1. Currently in the
+ ballpark of around 15%.
+* API breakage. If you can't afford modifying your code to adhere to the new API
+ and don't care too much about the new features, v2 is probably not for you.
+* Several bug fixes are trailing behind and still need to be forward-ported to
+ v2. See issue [#348](https://github.com/russross/blackfriday/issues/348) for
+ tracking.
+
+If you are still interested in the legacy `v1`, you can import it from
+`github.com/russross/blackfriday`. Documentation for the legacy v1 can be found
+here: https://godoc.org/github.com/russross/blackfriday
+
+### Known issue with `dep`
+
+There is a known problem with using Blackfriday v1 _transitively_ and `dep`.
+Currently `dep` prioritizes semver versions over anything else, and picks the
+latest one, plus it does not apply a `[[constraint]]` specifier to transitively
+pulled in packages. So if you're using something that uses Blackfriday v1, but
+that something does not use `dep` yet, you will get Blackfriday v2 pulled in and
+your first dependency will fail to build.
+
+There are couple of fixes for it, documented here:
+https://github.com/golang/dep/blob/master/docs/FAQ.md#how-do-i-constrain-a-transitive-dependencys-version
+
+Meanwhile, `dep` team is working on a more general solution to the constraints
+on transitive dependencies problem: https://github.com/golang/dep/issues/1124.
+
+
+Usage
+-----
+
+### v1
+
+For basic usage, it is as simple as getting your input into a byte
+slice and calling:
+
+ output := blackfriday.MarkdownBasic(input)
+
+This renders it with no extensions enabled. To get a more useful
+feature set, use this instead:
+
+ output := blackfriday.MarkdownCommon(input)
+
+### v2
+
+For the most sensible markdown processing, it is as simple as getting your input
+into a byte slice and calling:
+
+```go
+output := blackfriday.Run(input)
+```
+
+Your input will be parsed and the output rendered with a set of most popular
+extensions enabled. If you want the most basic feature set, corresponding with
+the bare Markdown specification, use:
+
+```go
+output := blackfriday.Run(input, blackfriday.WithNoExtensions())
+```
+
+### Sanitize untrusted content
+
+Blackfriday itself does nothing to protect against malicious content. If you are
+dealing with user-supplied markdown, we recommend running Blackfriday's output
+through HTML sanitizer such as [Bluemonday][5].
+
+Here's an example of simple usage of Blackfriday together with Bluemonday:
+
+```go
+import (
+ "github.com/microcosm-cc/bluemonday"
+ "gopkg.in/russross/blackfriday.v2"
+)
+
+// ...
+unsafe := blackfriday.Run(input)
+html := bluemonday.UGCPolicy().SanitizeBytes(unsafe)
+```
+
+### Custom options, v1
+
+If you want to customize the set of options, first get a renderer
+(currently only the HTML output engine), then use it to
+call the more general `Markdown` function. For examples, see the
+implementations of `MarkdownBasic` and `MarkdownCommon` in
+`markdown.go`.
+
+### Custom options, v2
+
+If you want to customize the set of options, use `blackfriday.WithExtensions`,
+`blackfriday.WithRenderer` and `blackfriday.WithRefOverride`.
+
+### `blackfriday-tool`
+
+You can also check out `blackfriday-tool` for a more complete example
+of how to use it. Download and install it using:
+
+ go get github.com/russross/blackfriday-tool
+
+This is a simple command-line tool that allows you to process a
+markdown file using a standalone program. You can also browse the
+source directly on github if you are just looking for some example
+code:
+
+* <http://github.com/russross/blackfriday-tool>
+
+Note that if you have not already done so, installing
+`blackfriday-tool` will be sufficient to download and install
+blackfriday in addition to the tool itself. The tool binary will be
+installed in `$GOPATH/bin`. This is a statically-linked binary that
+can be copied to wherever you need it without worrying about
+dependencies and library versions.
+
+### Sanitized anchor names
+
+Blackfriday includes an algorithm for creating sanitized anchor names
+corresponding to a given input text. This algorithm is used to create
+anchors for headings when `EXTENSION_AUTO_HEADER_IDS` is enabled. The
+algorithm has a specification, so that other packages can create
+compatible anchor names and links to those anchors.
+
+The specification is located at https://godoc.org/github.com/russross/blackfriday#hdr-Sanitized_Anchor_Names.
+
+[`SanitizedAnchorName`](https://godoc.org/github.com/russross/blackfriday#SanitizedAnchorName) exposes this functionality, and can be used to
+create compatible links to the anchor names generated by blackfriday.
+This algorithm is also implemented in a small standalone package at
+[`github.com/shurcooL/sanitized_anchor_name`](https://godoc.org/github.com/shurcooL/sanitized_anchor_name). It can be useful for clients
+that want a small package and don't need full functionality of blackfriday.
+
+
+Features
+--------
+
+All features of Sundown are supported, including:
+
+* **Compatibility**. The Markdown v1.0.3 test suite passes with
+ the `--tidy` option. Without `--tidy`, the differences are
+ mostly in whitespace and entity escaping, where blackfriday is
+ more consistent and cleaner.
+
+* **Common extensions**, including table support, fenced code
+ blocks, autolinks, strikethroughs, non-strict emphasis, etc.
+
+* **Safety**. Blackfriday is paranoid when parsing, making it safe
+ to feed untrusted user input without fear of bad things
+ happening. The test suite stress tests this and there are no
+ known inputs that make it crash. If you find one, please let me
+ know and send me the input that does it.
+
+ NOTE: "safety" in this context means *runtime safety only*. In order to
+ protect yourself against JavaScript injection in untrusted content, see
+ [this example](https://github.com/russross/blackfriday#sanitize-untrusted-content).
+
+* **Fast processing**. It is fast enough to render on-demand in
+ most web applications without having to cache the output.
+
+* **Thread safety**. You can run multiple parsers in different
+ goroutines without ill effect. There is no dependence on global
+ shared state.
+
+* **Minimal dependencies**. Blackfriday only depends on standard
+ library packages in Go. The source code is pretty
+ self-contained, so it is easy to add to any project, including
+ Google App Engine projects.
+
+* **Standards compliant**. Output successfully validates using the
+ W3C validation tool for HTML 4.01 and XHTML 1.0 Transitional.
+
+
+Extensions
+----------
+
+In addition to the standard markdown syntax, this package
+implements the following extensions:
+
+* **Intra-word emphasis supression**. The `_` character is
+ commonly used inside words when discussing code, so having
+ markdown interpret it as an emphasis command is usually the
+ wrong thing. Blackfriday lets you treat all emphasis markers as
+ normal characters when they occur inside a word.
+
+* **Tables**. Tables can be created by drawing them in the input
+ using a simple syntax:
+
+ ```
+ Name | Age
+ --------|------
+ Bob | 27
+ Alice | 23
+ ```
+
+* **Fenced code blocks**. In addition to the normal 4-space
+ indentation to mark code blocks, you can explicitly mark them
+ and supply a language (to make syntax highlighting simple). Just
+ mark it like this:
+
+ ``` go
+ func getTrue() bool {
+ return true
+ }
+ ```
+
+ You can use 3 or more backticks to mark the beginning of the
+ block, and the same number to mark the end of the block.
+
+ To preserve classes of fenced code blocks while using the bluemonday
+ HTML sanitizer, use the following policy:
+
+ ``` go
+ p := bluemonday.UGCPolicy()
+ p.AllowAttrs("class").Matching(regexp.MustCompile("^language-[a-zA-Z0-9]+$")).OnElements("code")
+ html := p.SanitizeBytes(unsafe)
+ ```
+
+* **Definition lists**. A simple definition list is made of a single-line
+ term followed by a colon and the definition for that term.
+
+ Cat
+ : Fluffy animal everyone likes
+
+ Internet
+ : Vector of transmission for pictures of cats
+
+ Terms must be separated from the previous definition by a blank line.
+
+* **Footnotes**. A marker in the text that will become a superscript number;
+ a footnote definition that will be placed in a list of footnotes at the
+ end of the document. A footnote looks like this:
+
+ This is a footnote.[^1]
+
+ [^1]: the footnote text.
+
+* **Autolinking**. Blackfriday can find URLs that have not been
+ explicitly marked as links and turn them into links.
+
+* **Strikethrough**. Use two tildes (`~~`) to mark text that
+ should be crossed out.
+
+* **Hard line breaks**. With this extension enabled (it is off by
+ default in the `MarkdownBasic` and `MarkdownCommon` convenience
+ functions), newlines in the input translate into line breaks in
+ the output.
+
+* **Smart quotes**. Smartypants-style punctuation substitution is
+ supported, turning normal double- and single-quote marks into
+ curly quotes, etc.
+
+* **LaTeX-style dash parsing** is an additional option, where `--`
+ is translated into `&ndash;`, and `---` is translated into
+ `&mdash;`. This differs from most smartypants processors, which
+ turn a single hyphen into an ndash and a double hyphen into an
+ mdash.
+
+* **Smart fractions**, where anything that looks like a fraction
+ is translated into suitable HTML (instead of just a few special
+ cases like most smartypant processors). For example, `4/5`
+ becomes `<sup>4</sup>&frasl;<sub>5</sub>`, which renders as
+ <sup>4</sup>&frasl;<sub>5</sub>.
+
+
+Other renderers
+---------------
+
+Blackfriday is structured to allow alternative rendering engines. Here
+are a few of note:
+
+* [github_flavored_markdown](https://godoc.org/github.com/shurcooL/github_flavored_markdown):
+ provides a GitHub Flavored Markdown renderer with fenced code block
+ highlighting, clickable heading anchor links.
+
+ It's not customizable, and its goal is to produce HTML output
+ equivalent to the [GitHub Markdown API endpoint](https://developer.github.com/v3/markdown/#render-a-markdown-document-in-raw-mode),
+ except the rendering is performed locally.
+
+* [markdownfmt](https://github.com/shurcooL/markdownfmt): like gofmt,
+ but for markdown.
+
+* [LaTeX output](https://bitbucket.org/ambrevar/blackfriday-latex):
+ renders output as LaTeX.
+
+
+TODO
+----
+
+* More unit testing
+* Improve Unicode support. It does not understand all Unicode
+ rules (about what constitutes a letter, a punctuation symbol,
+ etc.), so it may fail to detect word boundaries correctly in
+ some instances. It is safe on all UTF-8 input.
+
+
+License
+-------
+
+[Blackfriday is distributed under the Simplified BSD License](LICENSE.txt)
+
+
+ [1]: https://daringfireball.net/projects/markdown/ "Markdown"
+ [2]: https://golang.org/ "Go Language"
+ [3]: https://github.com/vmg/sundown "Sundown"
+ [4]: https://godoc.org/gopkg.in/russross/blackfriday.v2#Parse "Parse func"
+ [5]: https://github.com/microcosm-cc/bluemonday "Bluemonday"
+ [6]: https://labix.org/gopkg.in "gopkg.in"
+ [7]: https://github.com/golang/dep/ "dep"
+ [8]: https://github.com/Masterminds/glide "Glide"
+
+ [BuildSVG]: https://travis-ci.org/russross/blackfriday.svg?branch=master
+ [BuildURL]: https://travis-ci.org/russross/blackfriday
+ [GodocV2SVG]: https://godoc.org/gopkg.in/russross/blackfriday.v2?status.svg
+ [GodocV2URL]: https://godoc.org/gopkg.in/russross/blackfriday.v2
diff --git a/vendor/github.com/russross/blackfriday/block.go b/vendor/github.com/russross/blackfriday/block.go
index 9cf451f0..7fc731d5 100644
--- a/vendor/github.com/russross/blackfriday/block.go
+++ b/vendor/github.com/russross/blackfriday/block.go
@@ -15,8 +15,7 @@ package blackfriday
import (
"bytes"
-
- "github.com/shurcooL/sanitized_anchor_name"
+ "unicode"
)
// Parse block-level data.
@@ -243,7 +242,7 @@ func (p *parser) prefixHeader(out *bytes.Buffer, data []byte) int {
}
if end > i {
if id == "" && p.flags&EXTENSION_AUTO_HEADER_IDS != 0 {
- id = sanitized_anchor_name.Create(string(data[i:end]))
+ id = SanitizedAnchorName(string(data[i:end]))
}
work := func() bool {
p.inline(out, data[i:end])
@@ -1364,7 +1363,7 @@ func (p *parser) paragraph(out *bytes.Buffer, data []byte) int {
id := ""
if p.flags&EXTENSION_AUTO_HEADER_IDS != 0 {
- id = sanitized_anchor_name.Create(string(data[prev:eol]))
+ id = SanitizedAnchorName(string(data[prev:eol]))
}
p.r.Header(out, work, level, id)
@@ -1428,3 +1427,24 @@ func (p *parser) paragraph(out *bytes.Buffer, data []byte) int {
p.renderParagraph(out, data[:i])
return i
}
+
+// SanitizedAnchorName returns a sanitized anchor name for the given text.
+//
+// It implements the algorithm specified in the package comment.
+func SanitizedAnchorName(text string) string {
+ var anchorName []rune
+ futureDash := false
+ for _, r := range text {
+ switch {
+ case unicode.IsLetter(r) || unicode.IsNumber(r):
+ if futureDash && len(anchorName) > 0 {
+ anchorName = append(anchorName, '-')
+ }
+ futureDash = false
+ anchorName = append(anchorName, unicode.ToLower(r))
+ default:
+ futureDash = true
+ }
+ }
+ return string(anchorName)
+}
diff --git a/vendor/github.com/russross/blackfriday/doc.go b/vendor/github.com/russross/blackfriday/doc.go
new file mode 100644
index 00000000..9656c42a
--- /dev/null
+++ b/vendor/github.com/russross/blackfriday/doc.go
@@ -0,0 +1,32 @@
+// Package blackfriday is a Markdown processor.
+//
+// It translates plain text with simple formatting rules into HTML or LaTeX.
+//
+// Sanitized Anchor Names
+//
+// Blackfriday includes an algorithm for creating sanitized anchor names
+// corresponding to a given input text. This algorithm is used to create
+// anchors for headings when EXTENSION_AUTO_HEADER_IDS is enabled. The
+// algorithm is specified below, so that other packages can create
+// compatible anchor names and links to those anchors.
+//
+// The algorithm iterates over the input text, interpreted as UTF-8,
+// one Unicode code point (rune) at a time. All runes that are letters (category L)
+// or numbers (category N) are considered valid characters. They are mapped to
+// lower case, and included in the output. All other runes are considered
+// invalid characters. Invalid characters that preceed the first valid character,
+// as well as invalid character that follow the last valid character
+// are dropped completely. All other sequences of invalid characters
+// between two valid characters are replaced with a single dash character '-'.
+//
+// SanitizedAnchorName exposes this functionality, and can be used to
+// create compatible links to the anchor names generated by blackfriday.
+// This algorithm is also implemented in a small standalone package at
+// github.com/shurcooL/sanitized_anchor_name. It can be useful for clients
+// that want a small package and don't need full functionality of blackfriday.
+package blackfriday
+
+// NOTE: Keep Sanitized Anchor Name algorithm in sync with package
+// github.com/shurcooL/sanitized_anchor_name.
+// Otherwise, users of sanitized_anchor_name will get anchor names
+// that are incompatible with those generated by blackfriday.
diff --git a/vendor/github.com/russross/blackfriday/html.go b/vendor/github.com/russross/blackfriday/html.go
index 74e67ee8..c917c7d3 100644
--- a/vendor/github.com/russross/blackfriday/html.go
+++ b/vendor/github.com/russross/blackfriday/html.go
@@ -42,6 +42,7 @@ const (
HTML_SMARTYPANTS_DASHES // enable smart dashes (with HTML_USE_SMARTYPANTS)
HTML_SMARTYPANTS_LATEX_DASHES // enable LaTeX-style dashes (with HTML_USE_SMARTYPANTS and HTML_SMARTYPANTS_DASHES)
HTML_SMARTYPANTS_ANGLED_QUOTES // enable angled double quotes (with HTML_USE_SMARTYPANTS) for double quotes rendering
+ HTML_SMARTYPANTS_QUOTES_NBSP // enable "French guillemets" (with HTML_USE_SMARTYPANTS)
HTML_FOOTNOTE_RETURN_LINKS // generate a link at the end of a footnote to return to the source
)
@@ -619,7 +620,7 @@ func (options *Html) FootnoteRef(out *bytes.Buffer, ref []byte, id int) {
out.WriteString(`fnref:`)
out.WriteString(options.parameters.FootnoteAnchorPrefix)
out.Write(slug)
- out.WriteString(`"><a rel="footnote" href="#`)
+ out.WriteString(`"><a href="#`)
out.WriteString(`fn:`)
out.WriteString(options.parameters.FootnoteAnchorPrefix)
out.Write(slug)
diff --git a/vendor/github.com/russross/blackfriday/inline.go b/vendor/github.com/russross/blackfriday/inline.go
index cb00ed68..4483b8f1 100644
--- a/vendor/github.com/russross/blackfriday/inline.go
+++ b/vendor/github.com/russross/blackfriday/inline.go
@@ -170,6 +170,10 @@ func lineBreak(p *parser, out *bytes.Buffer, data []byte, offset int) int {
precededByBackslash := offset >= 1 && data[offset-1] == '\\' // see http://spec.commonmark.org/0.18/#example-527
precededByBackslash = precededByBackslash && p.flags&EXTENSION_BACKSLASH_LINE_BREAK != 0
+ if p.flags&EXTENSION_JOIN_LINES != 0 {
+ return 1
+ }
+
// should there be a hard line break here?
if p.flags&EXTENSION_HARD_LINE_BREAK == 0 && !precededByTwoSpaces && !precededByBackslash {
return 0
@@ -484,6 +488,7 @@ func link(p *parser, out *bytes.Buffer, data []byte, offset int) int {
}
p.notes = append(p.notes, ref)
+ p.notesRecord[string(ref.link)] = struct{}{}
link = ref.link
title = ref.title
@@ -494,9 +499,10 @@ func link(p *parser, out *bytes.Buffer, data []byte, offset int) int {
return 0
}
- if t == linkDeferredFootnote {
+ if t == linkDeferredFootnote && !p.isFootnote(lr) {
lr.noteId = len(p.notes) + 1
p.notes = append(p.notes, lr)
+ p.notesRecord[string(lr.link)] = struct{}{}
}
// keep link and title from reference
diff --git a/vendor/github.com/russross/blackfriday/markdown.go b/vendor/github.com/russross/blackfriday/markdown.go
index 58ba68de..1722a738 100644
--- a/vendor/github.com/russross/blackfriday/markdown.go
+++ b/vendor/github.com/russross/blackfriday/markdown.go
@@ -13,9 +13,6 @@
//
//
-// Blackfriday markdown processor.
-//
-// Translates plain text with simple formatting rules into HTML or LaTeX.
package blackfriday
import (
@@ -46,6 +43,7 @@ const (
EXTENSION_AUTO_HEADER_IDS // Create the header ID from the text
EXTENSION_BACKSLASH_LINE_BREAK // translate trailing backslashes into line breaks
EXTENSION_DEFINITION_LISTS // render definition lists
+ EXTENSION_JOIN_LINES // delete newline and join lines
commonHtmlFlags = 0 |
HTML_USE_XHTML |
@@ -220,7 +218,8 @@ type parser struct {
// Footnotes need to be ordered as well as available to quickly check for
// presence. If a ref is also a footnote, it's stored both in refs and here
// in notes. Slice is nil if footnotes not enabled.
- notes []*reference
+ notes []*reference
+ notesRecord map[string]struct{}
}
func (p *parser) getRef(refid string) (ref *reference, found bool) {
@@ -243,6 +242,11 @@ func (p *parser) getRef(refid string) (ref *reference, found bool) {
return ref, found
}
+func (p *parser) isFootnote(ref *reference) bool {
+ _, ok := p.notesRecord[string(ref.link)]
+ return ok
+}
+
//
//
// Public interface
@@ -378,6 +382,7 @@ func MarkdownOptions(input []byte, renderer Renderer, opts Options) []byte {
if extensions&EXTENSION_FOOTNOTES != 0 {
p.notes = make([]*reference, 0)
+ p.notesRecord = make(map[string]struct{})
}
first := firstPass(p, input)
diff --git a/vendor/github.com/russross/blackfriday/smartypants.go b/vendor/github.com/russross/blackfriday/smartypants.go
index eeffa5e1..f25bd07d 100644
--- a/vendor/github.com/russross/blackfriday/smartypants.go
+++ b/vendor/github.com/russross/blackfriday/smartypants.go
@@ -39,7 +39,7 @@ func isdigit(c byte) bool {
return c >= '0' && c <= '9'
}
-func smartQuoteHelper(out *bytes.Buffer, previousChar byte, nextChar byte, quote byte, isOpen *bool) bool {
+func smartQuoteHelper(out *bytes.Buffer, previousChar byte, nextChar byte, quote byte, isOpen *bool, addNBSP bool) bool {
// edge of the buffer is likely to be a tag that we don't get to see,
// so we treat it like text sometimes
@@ -96,6 +96,12 @@ func smartQuoteHelper(out *bytes.Buffer, previousChar byte, nextChar byte, quote
*isOpen = false
}
+ // Note that with the limited lookahead, this non-breaking
+ // space will also be appended to single double quotes.
+ if addNBSP && !*isOpen {
+ out.WriteString("&nbsp;")
+ }
+
out.WriteByte('&')
if *isOpen {
out.WriteByte('l')
@@ -104,6 +110,11 @@ func smartQuoteHelper(out *bytes.Buffer, previousChar byte, nextChar byte, quote
}
out.WriteByte(quote)
out.WriteString("quo;")
+
+ if addNBSP && *isOpen {
+ out.WriteString("&nbsp;")
+ }
+
return true
}
@@ -116,7 +127,7 @@ func smartSingleQuote(out *bytes.Buffer, smrt *smartypantsData, previousChar byt
if len(text) >= 3 {
nextChar = text[2]
}
- if smartQuoteHelper(out, previousChar, nextChar, 'd', &smrt.inDoubleQuote) {
+ if smartQuoteHelper(out, previousChar, nextChar, 'd', &smrt.inDoubleQuote, false) {
return 1
}
}
@@ -141,7 +152,7 @@ func smartSingleQuote(out *bytes.Buffer, smrt *smartypantsData, previousChar byt
if len(text) > 1 {
nextChar = text[1]
}
- if smartQuoteHelper(out, previousChar, nextChar, 's', &smrt.inSingleQuote) {
+ if smartQuoteHelper(out, previousChar, nextChar, 's', &smrt.inSingleQuote, false) {
return 0
}
@@ -205,13 +216,13 @@ func smartDashLatex(out *bytes.Buffer, smrt *smartypantsData, previousChar byte,
return 0
}
-func smartAmpVariant(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte, quote byte) int {
+func smartAmpVariant(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte, quote byte, addNBSP bool) int {
if bytes.HasPrefix(text, []byte("&quot;")) {
nextChar := byte(0)
if len(text) >= 7 {
nextChar = text[6]
}
- if smartQuoteHelper(out, previousChar, nextChar, quote, &smrt.inDoubleQuote) {
+ if smartQuoteHelper(out, previousChar, nextChar, quote, &smrt.inDoubleQuote, addNBSP) {
return 5
}
}
@@ -224,12 +235,15 @@ func smartAmpVariant(out *bytes.Buffer, smrt *smartypantsData, previousChar byte
return 0
}
-func smartAmp(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
- return smartAmpVariant(out, smrt, previousChar, text, 'd')
-}
+func smartAmp(angledQuotes, addNBSP bool) func(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
+ var quote byte = 'd'
+ if angledQuotes {
+ quote = 'a'
+ }
-func smartAmpAngledQuote(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
- return smartAmpVariant(out, smrt, previousChar, text, 'a')
+ return func(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
+ return smartAmpVariant(out, smrt, previousChar, text, quote, addNBSP)
+ }
}
func smartPeriod(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
@@ -253,7 +267,7 @@ func smartBacktick(out *bytes.Buffer, smrt *smartypantsData, previousChar byte,
if len(text) >= 3 {
nextChar = text[2]
}
- if smartQuoteHelper(out, previousChar, nextChar, 'd', &smrt.inDoubleQuote) {
+ if smartQuoteHelper(out, previousChar, nextChar, 'd', &smrt.inDoubleQuote, false) {
return 1
}
}
@@ -337,7 +351,7 @@ func smartDoubleQuoteVariant(out *bytes.Buffer, smrt *smartypantsData, previousC
if len(text) > 1 {
nextChar = text[1]
}
- if !smartQuoteHelper(out, previousChar, nextChar, quote, &smrt.inDoubleQuote) {
+ if !smartQuoteHelper(out, previousChar, nextChar, quote, &smrt.inDoubleQuote, false) {
out.WriteString("&quot;")
}
@@ -367,14 +381,30 @@ type smartCallback func(out *bytes.Buffer, smrt *smartypantsData, previousChar b
type smartypantsRenderer [256]smartCallback
+var (
+ smartAmpAngled = smartAmp(true, false)
+ smartAmpAngledNBSP = smartAmp(true, true)
+ smartAmpRegular = smartAmp(false, false)
+ smartAmpRegularNBSP = smartAmp(false, true)
+)
+
func smartypants(flags int) *smartypantsRenderer {
r := new(smartypantsRenderer)
+ addNBSP := flags&HTML_SMARTYPANTS_QUOTES_NBSP != 0
if flags&HTML_SMARTYPANTS_ANGLED_QUOTES == 0 {
r['"'] = smartDoubleQuote
- r['&'] = smartAmp
+ if !addNBSP {
+ r['&'] = smartAmpRegular
+ } else {
+ r['&'] = smartAmpRegularNBSP
+ }
} else {
r['"'] = smartAngledDoubleQuote
- r['&'] = smartAmpAngledQuote
+ if !addNBSP {
+ r['&'] = smartAmpAngled
+ } else {
+ r['&'] = smartAmpAngledNBSP
+ }
}
r['\''] = smartSingleQuote
r['('] = smartParens