From af7ffaa2798148e2a1b249da2330200bc032d7b1 Mon Sep 17 00:00:00 2001 From: mrsdizzie Date: Tue, 30 Jun 2020 17:34:03 -0400 Subject: Server-side syntax highlighting for all code (#12047) * Server-side syntax hilighting for all code This PR does a few things: * Remove all traces of highlight.js * Use chroma library to provide fast syntax hilighting directly on the server * Provide syntax hilighting for diffs * Re-style both unified and split diffs views * Add custom syntax hilighting styling for both regular and arc-green Fixes #7729 Fixes #10157 Fixes #11825 Fixes #7728 Fixes #3872 Fixes #3682 And perhaps gets closer to #9553 * fix line marker * fix repo search * Fix single line select * properly load settings * npm uninstall highlight.js * review suggestion * code review * forgot to call function * fix test * Apply suggestions from code review suggestions from @silverwind thanks Co-authored-by: silverwind * code review * copy/paste error * Use const for highlight size limit * Update web_src/less/_repository.less Co-authored-by: Lauris BH * update size limit to 1MB and other styling tweaks * fix highlighting for certain diff sections * fix test * add worker back as suggested Co-authored-by: silverwind Co-authored-by: Lauris BH --- modules/markup/markdown/markdown.go | 26 ++++++++++++++++++++++++++ modules/markup/sanitizer.go | 8 ++++---- 2 files changed, 30 insertions(+), 4 deletions(-) (limited to 'modules/markup') diff --git a/modules/markup/markdown/markdown.go b/modules/markup/markdown/markdown.go index 128268bc88..9197dd2fe1 100644 --- a/modules/markup/markdown/markdown.go +++ b/modules/markup/markdown/markdown.go @@ -15,7 +15,9 @@ import ( "code.gitea.io/gitea/modules/setting" giteautil "code.gitea.io/gitea/modules/util" + chromahtml "github.com/alecthomas/chroma/formatters/html" "github.com/yuin/goldmark" + "github.com/yuin/goldmark-highlighting" meta "github.com/yuin/goldmark-meta" "github.com/yuin/goldmark/extension" "github.com/yuin/goldmark/parser" @@ -49,6 +51,30 @@ func render(body []byte, urlPrefix string, metas map[string]string, wikiMarkdown extension.TaskList, extension.DefinitionList, common.FootnoteExtension, + highlighting.NewHighlighting( + highlighting.WithFormatOptions( + chromahtml.WithClasses(true), + chromahtml.PreventSurroundingPre(true), + ), + highlighting.WithWrapperRenderer(func(w util.BufWriter, c highlighting.CodeBlockContext, entering bool) { + language, _ := c.Language() + if language == nil { + language = []byte("text") + } + if entering { + // include language-x class as part of commonmark spec + _, err := w.WriteString("
")
+							if err != nil {
+								return
+							}
+						} else {
+							_, err := w.WriteString("
") + if err != nil { + return + } + } + }), + ), meta.Meta, ), goldmark.WithParserOptions( diff --git a/modules/markup/sanitizer.go b/modules/markup/sanitizer.go index 1041d56a32..e5f6e75084 100644 --- a/modules/markup/sanitizer.go +++ b/modules/markup/sanitizer.go @@ -37,8 +37,8 @@ func NewSanitizer() { // ReplaceSanitizer replaces the current sanitizer to account for changes in settings func ReplaceSanitizer() { sanitizer.policy = bluemonday.UGCPolicy() - // We only want to allow HighlightJS specific classes for code blocks - sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`^language-[\w-]+$`)).OnElements("code") + // For Chroma markdown plugin + sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`^(chroma )?language-[\w-]+$`)).OnElements("code") // Checkboxes sanitizer.policy.AllowAttrs("type").Matching(regexp.MustCompile(`^checkbox$`)).OnElements("input") @@ -65,8 +65,8 @@ func ReplaceSanitizer() { // Allow classes for emojis sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`emoji`)).OnElements("img") - // Allow icons, checkboxes and emojis on span - sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`^((icon(\s+[\p{L}\p{N}_-]+)+)|(ui checkbox)|(ui checked checkbox)|(emoji))$`)).OnElements("span") + // Allow icons, checkboxes, emojis, and chroma syntax on span + sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`^((icon(\s+[\p{L}\p{N}_-]+)+)|(ui checkbox)|(ui checked checkbox)|(emoji))$|^([a-z][a-z0-9]{0,2})$`)).OnElements("span") // Allow generally safe attributes generalSafeAttrs := []string{"abbr", "accept", "accept-charset", -- cgit v1.2.3