{"action":"created","comment":{"url":"https://api.github.com/repos/gogits/gogs/pulls/comments/36320391","id":36320391,"diff_hunk":"@@ -250,6 +250,7 @@ func PostProcessMarkdown(rawHtml []byte, urlPrefix string) []byte {\n func RenderMarkdown(rawBytes []byte, urlPrefix string) []byte {\n \tresult := RenderRawMarkdown(rawBytes, urlPrefix)\n \tresult = PostProcessMarkdown(result, urlPrefix)\n+\tSanitizer.AllowAttrs(\"class\").Matching(regexp.MustCompile(`[\\p{L}\\p{N}\\s\\-_',:\\[\\]!\\./\\\\\\(\\)&]*`)).OnElements(\"code\")","path":"modules/base/markdown.go","position":4,"original_position":4,"commit_id":"1e594f00279246115ce0a190ac7b40d45b59dda0","original_commit_id":"1e594f00279246115ce0a190ac7b40d45b59dda0","user":{"login":"manfer","id":458420,"avatar_url":"https://avatars.githubusercontent.com/u/458420?v=3","gravatar_id":"","url":"https://api.github.com/users/manfer","html_url":"https://github.com/manfer","followers_url":"https://api.github.com/users/manfer/followers","following_url":"https://api.github.com/users/manfer/following{/other_user}","gists_url":"https://api.github.com/users/manfer/gists{/gist_id}","starred_url":"https://api.github.com/users/manfer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/manfer/subscriptions","organizations_url":"https://api.github.com/users/manfer/orgs","repos_url":"https://api.github.com/users/manfer/repos","events_url":"https://api.github.com/users/manfer/events{/privacy}","received_events_url":"https://api.github.com/users/manfer/received_events","type":"User","site_admin":false},"body":"Yes. It only needs to be done once. So maybe it is better to do it in other place. I tried in `tools.go` just after the line that initializes it but I got some error about that line of code not being allowed there outside a function and I inmediately thought my best option was to put it just in markdown.go. I'm too new to go to know a better place to put that line of code but probably there is a better place indeed.","created_at":"2015-08-05T16:11:23Z","updated_at":"2015-08-05T16:11:23Z","html_url":"https://github.com/gogits/gogs/pull/1440#discussion_r36320391","pull_request_url":"https://api.github.com/repos/gogits/gogs/pulls/1440","_links":{"self":{"href":"https://api.github.com/repos/gogits/gogs/pulls/comments/36320391"},"html":{"href":"https://github.com/gogits/gogs/pull/1440#discussion_r36320391"},"pull_request":{"href":"https://api.github.com/repos/gogits/gogs/pulls/1440"}}},"pull_request":{"url":"https://api.github.com/repos/gogits/gogs/pulls/1440","id":41673018,"html_url":"https://github.com/gogits/gogs/pull/1440","diff_url":"https://github.com/gogits/gogs/pull/1440.diff","patch_url":"https://github.com/gogits/gogs/pull/1440.patch","issue_url":"https://api.github.com/repos/gogits/gogs/issues/1440","number":1440,"state":"open","locked":false,"title":"syntax highlight with prism","user":{"login":"manfer","id":458420,"avatar_url":"https://avatars.githubusercontent.com/u/458420?v=3","gravatar_id":"","url":"https://api.github.com/users/manfer","html_url":"https://github.com/manfer","followers_url":"https://api.github.com/users/manfer/followers","following_url":"https://api.github.com/users/manfer/following{/other_user}","gists_url":"https://api.github.com/users/manfer/gists{/gist_id}","starred_url":"https://api.github.com/users/manfer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/manfer/subscriptions","organizations_url":"https://api.github.com/users/manfer/orgs","repos_url":"https://api.github.com/users/manfer/repos","events_url":"https://api.github.com/users/manfer/events{/privacy}","received_events_url":"https://api.github.com/users/manfer/received_events","type":"User","site_admin":false},"body":"New syntax highlight. Bye bye prettyprint, welcome prism.\r\n\r\nThis is an starting point for this pull request as it is going to be difficult it doesn't need some tweak.\r\n\r\nWhat is on it?\r\n\r\nFirst of all we need to relax sanitizer of markdown parse output to allow the class attribute on the code tag. This is done on markdown.go:\r\n```go\r\nSanitizer.AllowAttrs(\"class\").Matching(regexp.MustCompile(`[\\p{L}\\p{N}\\s\\-_',:\\[\\]!\\./\\\\\\(\\)&]*`)).OnElements(\"code\")\r\n```\r\nThe regexp is to protect against inyections. Regexp borrowed from the example provided for the title  attribute in [bluemonday readme policy building section](https://github.com/microcosm-cc/bluemonday#policy-building)\r\n\r\nOnce we have our code with the `language-xxx` class we can apply syntax highlight only and just only on those fenced code blocks with a specified language instead of trying to highlight just everything.\r\n\r\nThe highlight has to be applied to the file view and not only on markdown output. So the `templates/repo/view_file.tmpl` has been edited to start using prism too.\r\n\r\nBut for that to work we have to guess which programming language is on the file. That is done in `routers/repo/view.go` where the programming language is guessed from the file extension. I have included by now all languages supported by prism. The extensions/languages map included on `routers/repo/view.go` has to be reviewed as we can maybe include more extensions (for example xhtml, xslt, ... can be rendered as markup language). Besides the extensions are case sensitive so maybe we have to include some extensions in different case too. Needs to be case sensitive as for example we want to identify .c as C language but .C as objective-C.\r\n\r\nWhat is [Prism](http://prismjs.com/)?\r\n\r\nWell, it is a javascript syntax highlighting library which in my opinion is getting really good. It is growing on languages supported as there are already PRs for new languages and its functionality can be extended with plugins. It already has some useful plugins.\r\n\r\nThe way to get prism is by downloading a customizing version from the page provided by the project, [Customize and Download Prism](http://prismjs.com/download.html). I have downloaded a development version (meaning not minified) with prism core (mandatory), default theme, all programming languages supported, and line highlight, line numbers, file highlight, show language, highlight keywords plugins.\r\n\r\nI included the line highlight because it can be useful. I still don't know where but looks it can be. We need line numbers for sure. Show language is cool. Highlight keywords is great too and gives the oportunity to tweak the highlight CSS theme in the future a lot more. About, file highlight I decided not to use it as it will use ajax to read the file that has to be highlighted and not sure if it could be a security risk (probably not but I prefer to feed the code string to the pre tag in the template file).\r\n\r\nAfter I had `prism.js` and `prism.css` I include then on gogs. The CSS file has been tweaked for gogs as `public/ng/css/gogs-prism.css`\r\n\r\nThe rest on the pull request has been get rid of prettyprint js code and minor CSS tweaks to `markdown.less` and `repository.less`.\r\n\r\nWhat I'm not sure if needs to be edited?\r\n\r\nI'm not sure about `public/ng/js/gogs.js` line 137- `Gogs.renderCodeView`. Looks its purpose is to deal with diff code views and that is still working properly but if this is the case I would suggest changing it and applying it only to `.code-diff` class and not `.code-view` which is more generic.\r\n\r\nI would need to know more clearly the purpose of all that code.\r\n\r\nAnd I don't know if some of the changes I made have to be included too in other files. Well, now I realize I didn't compiled just markdown.less to create `public/css/markdown.css but that should be done anyway automatically later if I'm not wrong.\r\n\r\nBut I don't know about any other file as it always confuses me having in `public/ng` and `public`, css, js, less, folders. And the same on templates don't know if I would have to edit other head.tmpl file too.\r\n\r\nWell, in brief, **needs deep review**.","created_at":"2015-08-05T12:28:34Z","updated_at":"2015-08-05T16:11:23Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e17d4ad266e66205a0bed2d83cfede8ff10fe28a","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/gogits/gogs/pulls/1440/commits","review_comments_url":"https://api.github.com/repos/gogits/gogs/pulls/1440/comments","review_comment_url":"https://api.github.com/repos/gogits/gogs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/gogits/gogs/issues/1440/comments","statuses_url":"https://api.github.com/repos/gogits/gogs/statuses/1e594f00279246115ce0a190ac7b40d45b59dda0","head":{"label":"manfer:syntax-highlight","ref":"syntax-highlight","sha":"1e594f00279246115ce0a190ac7b40d45b59dda0","user":{"login":"manfer","id":458420,"avatar_url":"https://avatars.githubusercontent.com/u/458420?v=3","gravatar_id":"","url":"https://api.github.com/users/manfer","html_url":"https://github.com/manfer","followers_url":"https://api.github.com/users/manfer/followers","following_url":"https://api.github.com/users/manfer/following{/other_user}","gists_url":"https://api.github.com/users/manfer/gists{/gist_id}","starred_url":"https://api.github.com/users/manfer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/manfer/subscriptions","organizations_url":"https://api.github.com/users/manfer/orgs","repos_url":"https://api.github.com/users/manfer/repos","events_url":"https://api.github.com/users/manfer/events{/privacy}","received_events_url":"https://api.github.com/users/manfer/received_events","type":"User","site_admin":false},"repo":{"id":39558830,"name":"gogs","full_name":"manfer/gogs","owner":{"login":"manfer","id":458420,"avatar_url":"https://avatars.githubusercontent.com/u/458420?v=3","gravatar_id":"","url":"https://api.github.com/users/manfer","html_url":"https://github.com/manfer","followers_url":"https://api.github.com/users/manfer/followers","following_url":"https://api.github.com/users/manfer/following{/other_user}","gists_url":"https://api.github.com/users/manfer/gists{/gist_id}","starred_url":"https://api.github.com/users/manfer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/manfer/subscriptions","organizations_url":"https://api.github.com/users/manfer/orgs","repos_url":"https://api.github.com/users/manfer/repos","events_url":"https://api.github.com/users/manfer/events{/privacy}","received_events_url":"https://api.github.com/users/manfer/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/manfer/gogs","description":"Gogs(Go Git Service) is a painless self-hosted Git Service.","fork":true,"url":"https://api.github.com/repos/manfer/gogs","forks_url":"https://api.github.com/repos/manfer/gogs/forks","keys_url":"https://api.github.com/repos/manfer/gogs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/manfer/gogs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/manfer/gogs/teams","hooks_url":"https://api.github.com/repos/manfer/gogs/hooks","issue_events_url":"https://api.github.com/repos/manfer/gogs/issues/events{/number}","events_url":"https://api.github.com/repos/manfer/gogs/events","assignees_url":"https://api.github.com/repos/manfer/gogs/assignees{/user}","branches_url":"https://api.github.com/repos/manfer/gogs/branches{/branch}","tags_url":"https://api.github.com/repos/manfer/gogs/tags","blobs_url":"https://api.github.com/repos/manfer/gogs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/manfer/gogs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/manfer/gogs/git/refs{/sha}","trees_url":"https://api.github.com/repos/manfer/gogs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/manfer/gogs/statuses/{sha}","languages_url":"https://api.github.com/repos/manfer/gogs/languages","stargazers_url":"https://api.github.com/repos/manfer/gogs/stargazers","contributors_url":"https://api.github.com/repos/manfer/gogs/contributors","subscribers_url":"https://api.github.com/repos/manfer/gogs/subscribers","subscription_url":"https://api.github.com/repos/manfer/gogs/subscription","commits_url":"https://api.github.com/repos/manfer/gogs/commits{/sha}","git_commits_url":"https://api.github.com/repos/manfer/gogs/git/commits{/sha}","comments_url":"https://api.github.com/repos/manfer/gogs/comments{/number}","issue_comment_url":"https://api.github.com/repos/manfer/gogs/issues/comments{/number}","contents_url":"https://api.github.com/repos/manfer/gogs/contents/{+path}","compare_url":"https://api.github.com/repos/manfer/gogs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/manfer/gogs/merges","archive_url":"https://api.github.com/repos/manfer/gogs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/manfer/gogs/downloads","issues_url":"https://api.github.com/repos/manfer/gogs/issues{/number}","pulls_url":"https://api.github.com/repos/manfer/gogs/pulls{/number}","milestones_url":"https://api.github.com/repos/manfer/gogs/milestones{/number}","notifications_url":"https://api.github.com/repos/manfer/gogs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/manfer/gogs/labels{/name}","releases_url":"https://api.github.com/repos/manfer/gogs/releases{/id}","created_at":"2015-07-23T09:39:14Z","updated_at":"2015-07-23T09:39:16Z","pushed_at":"2015-08-05T14:07:31Z","git_url":"git://github.com/manfer/gogs.git","ssh_url":"git@github.com:manfer/gogs.git","clone_url":"https://github.com/manfer/gogs.git","svn_url":"https://github.com/manfer/gogs","homepage":"http://gogs.io","size":11641,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"gogits:develop","ref":"develop","sha":"9f12ab0e8847682a686fdb843922a761bbb5c225","user":{"login":"gogits","id":6656686,"avatar_url":"https://avatars.githubusercontent.com/u/6656686?v=3","gravatar_id":"","url":"https://api.github.com/users/gogits","html_url":"https://github.com/gogits","followers_url":"https://api.github.com/users/gogits/followers","following_url":"https://api.github.com/users/gogits/following{/other_user}","gists_url":"https://api.github.com/users/gogits/gists{/gist_id}","starred_url":"https://api.github.com/users/gogits/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gogits/subscriptions","organizations_url":"https://api.github.com/users/gogits/orgs","repos_url":"https://api.github.com/users/gogits/repos","events_url":"https://api.github.com/users/gogits/events{/privacy}","received_events_url":"https://api.github.com/users/gogits/received_events","type":"Organization","site_admin":false},"repo":{"id":16752620,"name":"gogs","full_name":"gogits/gogs","owner":{"login":"gogits","id":6656686,"avatar_url":"https://avatars.githubusercontent.com/u/6656686?v=3","gravatar_id":"","url":"https://api.github.com/users/gogits","html_url":"https://github.com/gogits","followers_url":"https://api.github.com/users/gogits/followers","following_url":"https://api.github.com/users/gogits/following{/other_user}","gists_url":"https://api.github.com/users/gogits/gists{/gist_id}","starred_url":"https://api.github.com/users/gogits/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gogits/subscriptions","organizations_url":"https://api.github.com/users/gogits/orgs","repos_url":"https://api.github.com/users/gogits/repos","events_url":"https://api.github.com/users/gogits/events{/privacy}","received_events_url":"https://api.github.com/users/gogits/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/gogits/gogs","description":"Gogs(Go Git Service) is a painless self-hosted Git Service.","fork":false,"url":"https://api.github.com/repos/gogits/gogs","forks_url":"https://api.github.com/repos/gogits/gogs/forks","keys_url":"https://api.github.com/repos/gogits/gogs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/gogits/gogs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/gogits/gogs/teams","hooks_url":"https://api.github.com/repos/gogits/gogs/hooks","issue_events_url":"https://api.github.com/repos/gogits/gogs/issues/events{/number}","events_url":"https://api.github.com/repos/gogits/gogs/events","assignees_url":"https://api.github.com/repos/gogits/gogs/assignees{/user}","branches_url":"https://api.github.com/repos/gogits/gogs/branches{/branch}","tags_url":"https://api.github.com/repos/gogits/gogs/tags","blobs_url":"https://api.github.com/repos/gogits/gogs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/gogits/gogs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/gogits/gogs/git/refs{/sha}","trees_url":"https://api.github.com/repos/gogits/gogs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/gogits/gogs/statuses/{sha}","languages_url":"https://api.github.com/repos/gogits/gogs/languages","stargazers_url":"https://api.github.com/repos/gogits/gogs/stargazers","contributors_url":"https://api.github.com/repos/gogits/gogs/contributors","subscribers_url":"https://api.github.com/repos/gogits/gogs/subscribers","subscription_url":"https://api.github.com/repos/gogits/gogs/subscription","commits_url":"https://api.github.com/repos/gogits/gogs/commits{/sha}","git_commits_url":"https://api.github.com/repos/gogits/gogs/git/commits{/sha}","comments_url":"https://api.github.com/repos/gogits/gogs/comments{/number}","issue_comment_url":"https://api.github.com/repos/gogits/gogs/issues/comments{/number}","contents_url":"https://api.github.com/repos/gogits/gogs/contents/{+path}","compare_url":"https://api.github.com/repos/gogits/gogs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/gogits/gogs/merges","archive_url":"https://api.github.com/repos/gogits/gogs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/gogits/gogs/downloads","issues_url":"https://api.github.com/repos/gogits/gogs/issues{/number}","pulls_url":"https://api.github.com/repos/gogits/gogs/pulls{/number}","milestones_url":"https://api.github.com/repos/gogits/gogs/milestones{/number}","notifications_url":"https://api.github.com/repos/gogits/gogs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/gogits/gogs/labels{/name}","releases_url":"https://api.github.com/repos/gogits/gogs/releases{/id}","created_at":"2014-02-12T01:57:08Z","updated_at":"2015-08-05T15:46:54Z","pushed_at":"2015-08-05T15:26:39Z","git_url":"git://github.com/gogits/gogs.git","ssh_url":"git@github.com:gogits/gogs.git","clone_url":"https://github.com/gogits/gogs.git","svn_url":"https://github.com/gogits/gogs","homepage":"http://gogs.io","size":20631,"stargazers_count":8162,"watchers_count":8162,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":697,"mirror_url":null,"open_issues_count":316,"forks":697,"open_issues":316,"watchers":8162,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/gogits/gogs/pulls/1440"},"html":{"href":"https://github.com/gogits/gogs/pull/1440"},"issue":{"href":"https://api.github.com/repos/gogits/gogs/issues/1440"},"comments":{"href":"https://api.github.com/repos/gogits/gogs/issues/1440/comments"},"review_comments":{"href":"https://api.github.com/repos/gogits/gogs/pulls/1440/comments"},"review_comment":{"href":"https://api.github.com/repos/gogits/gogs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/gogits/gogs/pulls/1440/commits"},"statuses":{"href":"https://api.github.com/repos/gogits/gogs/statuses/1e594f00279246115ce0a190ac7b40d45b59dda0"}}}}