github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/russross/blackfriday/latex.go (about)

     1  //
     2  // Blackfriday Markdown Processor
     3  // Available at http://yougam/libraries/russross/blackfriday
     4  //
     5  // Copyright © 2011 Russ Ross <russ@russross.com>.
     6  // Distributed under the Simplified BSD License.
     7  // See README.md for details.
     8  //
     9  
    10  //
    11  //
    12  // LaTeX rendering backend
    13  //
    14  //
    15  
    16  package blackfriday
    17  
    18  import (
    19  	"bytes"
    20  )
    21  
    22  // Latex is a type that implements the Renderer interface for LaTeX output.
    23  //
    24  // Do not create this directly, instead use the LatexRenderer function.
    25  type Latex struct {
    26  }
    27  
    28  // LatexRenderer creates and configures a Latex object, which
    29  // satisfies the Renderer interface.
    30  //
    31  // flags is a set of LATEX_* options ORed together (currently no such options
    32  // are defined).
    33  func LatexRenderer(flags int) Renderer {
    34  	return &Latex{}
    35  }
    36  
    37  func (options *Latex) GetFlags() int {
    38  	return 0
    39  }
    40  
    41  // render code chunks using verbatim, or listings if we have a language
    42  func (options *Latex) BlockCode(out *bytes.Buffer, text []byte, lang string) {
    43  	if lang == "" {
    44  		out.WriteString("\n\\begin{verbatim}\n")
    45  	} else {
    46  		out.WriteString("\n\\begin{lstlisting}[language=")
    47  		out.WriteString(lang)
    48  		out.WriteString("]\n")
    49  	}
    50  	out.Write(text)
    51  	if lang == "" {
    52  		out.WriteString("\n\\end{verbatim}\n")
    53  	} else {
    54  		out.WriteString("\n\\end{lstlisting}\n")
    55  	}
    56  }
    57  
    58  func (options *Latex) TitleBlock(out *bytes.Buffer, text []byte) {
    59  
    60  }
    61  
    62  func (options *Latex) BlockQuote(out *bytes.Buffer, text []byte) {
    63  	out.WriteString("\n\\begin{quotation}\n")
    64  	out.Write(text)
    65  	out.WriteString("\n\\end{quotation}\n")
    66  }
    67  
    68  func (options *Latex) BlockHtml(out *bytes.Buffer, text []byte) {
    69  	// a pretty lame thing to do...
    70  	out.WriteString("\n\\begin{verbatim}\n")
    71  	out.Write(text)
    72  	out.WriteString("\n\\end{verbatim}\n")
    73  }
    74  
    75  func (options *Latex) Header(out *bytes.Buffer, text func() bool, level int, id string) {
    76  	marker := out.Len()
    77  
    78  	switch level {
    79  	case 1:
    80  		out.WriteString("\n\\section{")
    81  	case 2:
    82  		out.WriteString("\n\\subsection{")
    83  	case 3:
    84  		out.WriteString("\n\\subsubsection{")
    85  	case 4:
    86  		out.WriteString("\n\\paragraph{")
    87  	case 5:
    88  		out.WriteString("\n\\subparagraph{")
    89  	case 6:
    90  		out.WriteString("\n\\textbf{")
    91  	}
    92  	if !text() {
    93  		out.Truncate(marker)
    94  		return
    95  	}
    96  	out.WriteString("}\n")
    97  }
    98  
    99  func (options *Latex) HRule(out *bytes.Buffer) {
   100  	out.WriteString("\n\\HRule\n")
   101  }
   102  
   103  func (options *Latex) List(out *bytes.Buffer, text func() bool, flags int) {
   104  	marker := out.Len()
   105  	if flags&LIST_TYPE_ORDERED != 0 {
   106  		out.WriteString("\n\\begin{enumerate}\n")
   107  	} else {
   108  		out.WriteString("\n\\begin{itemize}\n")
   109  	}
   110  	if !text() {
   111  		out.Truncate(marker)
   112  		return
   113  	}
   114  	if flags&LIST_TYPE_ORDERED != 0 {
   115  		out.WriteString("\n\\end{enumerate}\n")
   116  	} else {
   117  		out.WriteString("\n\\end{itemize}\n")
   118  	}
   119  }
   120  
   121  func (options *Latex) ListItem(out *bytes.Buffer, text []byte, flags int) {
   122  	out.WriteString("\n\\item ")
   123  	out.Write(text)
   124  }
   125  
   126  func (options *Latex) Paragraph(out *bytes.Buffer, text func() bool) {
   127  	marker := out.Len()
   128  	out.WriteString("\n")
   129  	if !text() {
   130  		out.Truncate(marker)
   131  		return
   132  	}
   133  	out.WriteString("\n")
   134  }
   135  
   136  func (options *Latex) Table(out *bytes.Buffer, header []byte, body []byte, columnData []int) {
   137  	out.WriteString("\n\\begin{tabular}{")
   138  	for _, elt := range columnData {
   139  		switch elt {
   140  		case TABLE_ALIGNMENT_LEFT:
   141  			out.WriteByte('l')
   142  		case TABLE_ALIGNMENT_RIGHT:
   143  			out.WriteByte('r')
   144  		default:
   145  			out.WriteByte('c')
   146  		}
   147  	}
   148  	out.WriteString("}\n")
   149  	out.Write(header)
   150  	out.WriteString(" \\\\\n\\hline\n")
   151  	out.Write(body)
   152  	out.WriteString("\n\\end{tabular}\n")
   153  }
   154  
   155  func (options *Latex) TableRow(out *bytes.Buffer, text []byte) {
   156  	if out.Len() > 0 {
   157  		out.WriteString(" \\\\\n")
   158  	}
   159  	out.Write(text)
   160  }
   161  
   162  func (options *Latex) TableHeaderCell(out *bytes.Buffer, text []byte, align int) {
   163  	if out.Len() > 0 {
   164  		out.WriteString(" & ")
   165  	}
   166  	out.Write(text)
   167  }
   168  
   169  func (options *Latex) TableCell(out *bytes.Buffer, text []byte, align int) {
   170  	if out.Len() > 0 {
   171  		out.WriteString(" & ")
   172  	}
   173  	out.Write(text)
   174  }
   175  
   176  // TODO: this
   177  func (options *Latex) Footnotes(out *bytes.Buffer, text func() bool) {
   178  
   179  }
   180  
   181  func (options *Latex) FootnoteItem(out *bytes.Buffer, name, text []byte, flags int) {
   182  
   183  }
   184  
   185  func (options *Latex) AutoLink(out *bytes.Buffer, link []byte, kind int) {
   186  	out.WriteString("\\href{")
   187  	if kind == LINK_TYPE_EMAIL {
   188  		out.WriteString("mailto:")
   189  	}
   190  	out.Write(link)
   191  	out.WriteString("}{")
   192  	out.Write(link)
   193  	out.WriteString("}")
   194  }
   195  
   196  func (options *Latex) CodeSpan(out *bytes.Buffer, text []byte) {
   197  	out.WriteString("\\texttt{")
   198  	escapeSpecialChars(out, text)
   199  	out.WriteString("}")
   200  }
   201  
   202  func (options *Latex) DoubleEmphasis(out *bytes.Buffer, text []byte) {
   203  	out.WriteString("\\textbf{")
   204  	out.Write(text)
   205  	out.WriteString("}")
   206  }
   207  
   208  func (options *Latex) Emphasis(out *bytes.Buffer, text []byte) {
   209  	out.WriteString("\\textit{")
   210  	out.Write(text)
   211  	out.WriteString("}")
   212  }
   213  
   214  func (options *Latex) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {
   215  	if bytes.HasPrefix(link, []byte("http://")) || bytes.HasPrefix(link, []byte("https://")) {
   216  		// treat it like a link
   217  		out.WriteString("\\href{")
   218  		out.Write(link)
   219  		out.WriteString("}{")
   220  		out.Write(alt)
   221  		out.WriteString("}")
   222  	} else {
   223  		out.WriteString("\\includegraphics{")
   224  		out.Write(link)
   225  		out.WriteString("}")
   226  	}
   227  }
   228  
   229  func (options *Latex) LineBreak(out *bytes.Buffer) {
   230  	out.WriteString(" \\\\\n")
   231  }
   232  
   233  func (options *Latex) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) {
   234  	out.WriteString("\\href{")
   235  	out.Write(link)
   236  	out.WriteString("}{")
   237  	out.Write(content)
   238  	out.WriteString("}")
   239  }
   240  
   241  func (options *Latex) RawHtmlTag(out *bytes.Buffer, tag []byte) {
   242  }
   243  
   244  func (options *Latex) TripleEmphasis(out *bytes.Buffer, text []byte) {
   245  	out.WriteString("\\textbf{\\textit{")
   246  	out.Write(text)
   247  	out.WriteString("}}")
   248  }
   249  
   250  func (options *Latex) StrikeThrough(out *bytes.Buffer, text []byte) {
   251  	out.WriteString("\\sout{")
   252  	out.Write(text)
   253  	out.WriteString("}")
   254  }
   255  
   256  // TODO: this
   257  func (options *Latex) FootnoteRef(out *bytes.Buffer, ref []byte, id int) {
   258  
   259  }
   260  
   261  func needsBackslash(c byte) bool {
   262  	for _, r := range []byte("_{}%$&\\~#") {
   263  		if c == r {
   264  			return true
   265  		}
   266  	}
   267  	return false
   268  }
   269  
   270  func escapeSpecialChars(out *bytes.Buffer, text []byte) {
   271  	for i := 0; i < len(text); i++ {
   272  		// directly copy normal characters
   273  		org := i
   274  
   275  		for i < len(text) && !needsBackslash(text[i]) {
   276  			i++
   277  		}
   278  		if i > org {
   279  			out.Write(text[org:i])
   280  		}
   281  
   282  		// escape a character
   283  		if i >= len(text) {
   284  			break
   285  		}
   286  		out.WriteByte('\\')
   287  		out.WriteByte(text[i])
   288  	}
   289  }
   290  
   291  func (options *Latex) Entity(out *bytes.Buffer, entity []byte) {
   292  	// TODO: convert this into a unicode character or something
   293  	out.Write(entity)
   294  }
   295  
   296  func (options *Latex) NormalText(out *bytes.Buffer, text []byte) {
   297  	escapeSpecialChars(out, text)
   298  }
   299  
   300  // header and footer
   301  func (options *Latex) DocumentHeader(out *bytes.Buffer) {
   302  	out.WriteString("\\documentclass{article}\n")
   303  	out.WriteString("\n")
   304  	out.WriteString("\\usepackage{graphicx}\n")
   305  	out.WriteString("\\usepackage{listings}\n")
   306  	out.WriteString("\\usepackage[margin=1in]{geometry}\n")
   307  	out.WriteString("\\usepackage[utf8]{inputenc}\n")
   308  	out.WriteString("\\usepackage{verbatim}\n")
   309  	out.WriteString("\\usepackage[normalem]{ulem}\n")
   310  	out.WriteString("\\usepackage{hyperref}\n")
   311  	out.WriteString("\n")
   312  	out.WriteString("\\hypersetup{colorlinks,%\n")
   313  	out.WriteString("  citecolor=black,%\n")
   314  	out.WriteString("  filecolor=black,%\n")
   315  	out.WriteString("  linkcolor=black,%\n")
   316  	out.WriteString("  urlcolor=black,%\n")
   317  	out.WriteString("  pdfstartview=FitH,%\n")
   318  	out.WriteString("  breaklinks=true,%\n")
   319  	out.WriteString("  pdfauthor={Blackfriday Markdown Processor v")
   320  	out.WriteString(VERSION)
   321  	out.WriteString("}}\n")
   322  	out.WriteString("\n")
   323  	out.WriteString("\\newcommand{\\HRule}{\\rule{\\linewidth}{0.5mm}}\n")
   324  	out.WriteString("\\addtolength{\\parskip}{0.5\\baselineskip}\n")
   325  	out.WriteString("\\parindent=0pt\n")
   326  	out.WriteString("\n")
   327  	out.WriteString("\\begin{document}\n")
   328  }
   329  
   330  func (options *Latex) DocumentFooter(out *bytes.Buffer) {
   331  	out.WriteString("\n\\end{document}\n")
   332  }