|
- // Copyright 2019 The Gitea Authors. All rights reserved.
- // Use of this source code is governed by a MIT-style
- // license that can be found in the LICENSE file.
-
- package mdstripper
-
- import (
- "bytes"
-
- "github.com/russross/blackfriday"
- )
-
- // MarkdownStripper extends blackfriday.Renderer
- type MarkdownStripper struct {
- blackfriday.Renderer
- links []string
- coallesce bool
- }
-
- const (
- blackfridayExtensions = 0 |
- blackfriday.EXTENSION_NO_INTRA_EMPHASIS |
- blackfriday.EXTENSION_TABLES |
- blackfriday.EXTENSION_FENCED_CODE |
- blackfriday.EXTENSION_STRIKETHROUGH |
- blackfriday.EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK |
- blackfriday.EXTENSION_DEFINITION_LISTS |
- blackfriday.EXTENSION_FOOTNOTES |
- blackfriday.EXTENSION_HEADER_IDS |
- blackfriday.EXTENSION_AUTO_HEADER_IDS |
- // Not included in modules/markup/markdown/markdown.go;
- // required here to process inline links
- blackfriday.EXTENSION_AUTOLINK
- )
-
- //revive:disable:var-naming Implementing the Rendering interface requires breaking some linting rules
-
- // StripMarkdown parses markdown content by removing all markup and code blocks
- // in order to extract links and other references
- func StripMarkdown(rawBytes []byte) (string, []string) {
- stripper := &MarkdownStripper{
- links: make([]string, 0, 10),
- }
- body := blackfriday.Markdown(rawBytes, stripper, blackfridayExtensions)
- return string(body), stripper.GetLinks()
- }
-
- // StripMarkdownBytes parses markdown content by removing all markup and code blocks
- // in order to extract links and other references
- func StripMarkdownBytes(rawBytes []byte) ([]byte, []string) {
- stripper := &MarkdownStripper{
- links: make([]string, 0, 10),
- }
- body := blackfriday.Markdown(rawBytes, stripper, blackfridayExtensions)
- return body, stripper.GetLinks()
- }
-
- // block-level callbacks
-
- // BlockCode dummy function to proceed with rendering
- func (r *MarkdownStripper) BlockCode(out *bytes.Buffer, text []byte, infoString string) {
- // Not rendered
- r.coallesce = false
- }
-
- // BlockQuote dummy function to proceed with rendering
- func (r *MarkdownStripper) BlockQuote(out *bytes.Buffer, text []byte) {
- // FIXME: perhaps it's better to leave out block quote for this?
- r.processString(out, text, false)
- }
-
- // BlockHtml dummy function to proceed with rendering
- func (r *MarkdownStripper) BlockHtml(out *bytes.Buffer, text []byte) { //nolint
- // Not rendered
- r.coallesce = false
- }
-
- // Header dummy function to proceed with rendering
- func (r *MarkdownStripper) Header(out *bytes.Buffer, text func() bool, level int, id string) {
- text()
- r.coallesce = false
- }
-
- // HRule dummy function to proceed with rendering
- func (r *MarkdownStripper) HRule(out *bytes.Buffer) {
- // Not rendered
- r.coallesce = false
- }
-
- // List dummy function to proceed with rendering
- func (r *MarkdownStripper) List(out *bytes.Buffer, text func() bool, flags int) {
- text()
- r.coallesce = false
- }
-
- // ListItem dummy function to proceed with rendering
- func (r *MarkdownStripper) ListItem(out *bytes.Buffer, text []byte, flags int) {
- r.processString(out, text, false)
- }
-
- // Paragraph dummy function to proceed with rendering
- func (r *MarkdownStripper) Paragraph(out *bytes.Buffer, text func() bool) {
- text()
- r.coallesce = false
- }
-
- // Table dummy function to proceed with rendering
- func (r *MarkdownStripper) Table(out *bytes.Buffer, header []byte, body []byte, columnData []int) {
- r.processString(out, header, false)
- r.processString(out, body, false)
- }
-
- // TableRow dummy function to proceed with rendering
- func (r *MarkdownStripper) TableRow(out *bytes.Buffer, text []byte) {
- r.processString(out, text, false)
- }
-
- // TableHeaderCell dummy function to proceed with rendering
- func (r *MarkdownStripper) TableHeaderCell(out *bytes.Buffer, text []byte, flags int) {
- r.processString(out, text, false)
- }
-
- // TableCell dummy function to proceed with rendering
- func (r *MarkdownStripper) TableCell(out *bytes.Buffer, text []byte, flags int) {
- r.processString(out, text, false)
- }
-
- // Footnotes dummy function to proceed with rendering
- func (r *MarkdownStripper) Footnotes(out *bytes.Buffer, text func() bool) {
- text()
- }
-
- // FootnoteItem dummy function to proceed with rendering
- func (r *MarkdownStripper) FootnoteItem(out *bytes.Buffer, name, text []byte, flags int) {
- r.processString(out, text, false)
- }
-
- // TitleBlock dummy function to proceed with rendering
- func (r *MarkdownStripper) TitleBlock(out *bytes.Buffer, text []byte) {
- r.processString(out, text, false)
- }
-
- // Span-level callbacks
-
- // AutoLink dummy function to proceed with rendering
- func (r *MarkdownStripper) AutoLink(out *bytes.Buffer, link []byte, kind int) {
- r.processLink(out, link, []byte{})
- }
-
- // CodeSpan dummy function to proceed with rendering
- func (r *MarkdownStripper) CodeSpan(out *bytes.Buffer, text []byte) {
- // Not rendered
- r.coallesce = false
- }
-
- // DoubleEmphasis dummy function to proceed with rendering
- func (r *MarkdownStripper) DoubleEmphasis(out *bytes.Buffer, text []byte) {
- r.processString(out, text, false)
- }
-
- // Emphasis dummy function to proceed with rendering
- func (r *MarkdownStripper) Emphasis(out *bytes.Buffer, text []byte) {
- r.processString(out, text, false)
- }
-
- // Image dummy function to proceed with rendering
- func (r *MarkdownStripper) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {
- // Not rendered
- r.coallesce = false
- }
-
- // LineBreak dummy function to proceed with rendering
- func (r *MarkdownStripper) LineBreak(out *bytes.Buffer) {
- // Not rendered
- r.coallesce = false
- }
-
- // Link dummy function to proceed with rendering
- func (r *MarkdownStripper) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) {
- r.processLink(out, link, content)
- }
-
- // RawHtmlTag dummy function to proceed with rendering
- func (r *MarkdownStripper) RawHtmlTag(out *bytes.Buffer, tag []byte) { //nolint
- // Not rendered
- r.coallesce = false
- }
-
- // TripleEmphasis dummy function to proceed with rendering
- func (r *MarkdownStripper) TripleEmphasis(out *bytes.Buffer, text []byte) {
- r.processString(out, text, false)
- }
-
- // StrikeThrough dummy function to proceed with rendering
- func (r *MarkdownStripper) StrikeThrough(out *bytes.Buffer, text []byte) {
- r.processString(out, text, false)
- }
-
- // FootnoteRef dummy function to proceed with rendering
- func (r *MarkdownStripper) FootnoteRef(out *bytes.Buffer, ref []byte, id int) {
- // Not rendered
- r.coallesce = false
- }
-
- // Low-level callbacks
-
- // Entity dummy function to proceed with rendering
- func (r *MarkdownStripper) Entity(out *bytes.Buffer, entity []byte) {
- // FIXME: literal entities are not parsed; perhaps they should
- r.coallesce = false
- }
-
- // NormalText dummy function to proceed with rendering
- func (r *MarkdownStripper) NormalText(out *bytes.Buffer, text []byte) {
- r.processString(out, text, true)
- }
-
- // Header and footer
-
- // DocumentHeader dummy function to proceed with rendering
- func (r *MarkdownStripper) DocumentHeader(out *bytes.Buffer) {
- r.coallesce = false
- }
-
- // DocumentFooter dummy function to proceed with rendering
- func (r *MarkdownStripper) DocumentFooter(out *bytes.Buffer) {
- r.coallesce = false
- }
-
- // GetFlags returns rendering flags
- func (r *MarkdownStripper) GetFlags() int {
- return 0
- }
-
- //revive:enable:var-naming
-
- func doubleSpace(out *bytes.Buffer) {
- if out.Len() > 0 {
- out.WriteByte('\n')
- }
- }
-
- func (r *MarkdownStripper) processString(out *bytes.Buffer, text []byte, coallesce bool) {
- // Always break-up words
- if !coallesce || !r.coallesce {
- doubleSpace(out)
- }
- out.Write(text)
- r.coallesce = coallesce
- }
- func (r *MarkdownStripper) processLink(out *bytes.Buffer, link []byte, content []byte) {
- // Links are processed out of band
- r.links = append(r.links, string(link))
- r.coallesce = false
- }
-
- // GetLinks returns the list of link data collected while parsing
- func (r *MarkdownStripper) GetLinks() []string {
- return r.links
- }
|