From f4d7586034b50e0ffdebbb1702fe5201e2e76d9a Mon Sep 17 00:00:00 2001 From: Garen Torikian & Nathan Sobo Date: Thu, 2 May 2013 16:55:08 -0700 Subject: [PATCH] Refactor syntax highlighting of Markdown pre blocks Extract out editor-colors class to apply background and default text color Remove pre background coloring from Markdown preview stylesheet --- src/app/editor.coffee | 105 ++++++++++++++---- .../lib/markdown-preview-view.coffee | 24 +--- .../stylesheets/markdown-preview.less | 1 - 3 files changed, 90 insertions(+), 40 deletions(-) diff --git a/src/app/editor.coffee b/src/app/editor.coffee index 1b4f66761..f2e381bb0 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -43,7 +43,7 @@ class Editor extends View @div outlet: 'verticalScrollbarContent' @classes: ({mini} = {}) -> - classes = ['editor'] + classes = ['editor', 'editor-colors'] classes.push 'mini' if mini classes.join(' ') @@ -1317,35 +1317,25 @@ class Editor extends View buildLineElementsForScreenRows: (startRow, endRow) -> div = document.createElement('div') - div.innerHTML = @buildHtmlLines(startRow, endRow) + div.innerHTML = @htmlForScreenRows(startRow, endRow) new Array(div.children...) - buildHtmlLines: (startRow, endRow) -> + htmlForScreenRows: (startRow, endRow) -> lines = @activeEditSession.linesForScreenRows(startRow, endRow) htmlLines = [] screenRow = startRow for line in @activeEditSession.linesForScreenRows(startRow, endRow) - htmlLines.push(@buildHtmlFromLine(line, screenRow++)) + htmlLines.push(@htmlForScreenLine(line, screenRow++)) htmlLines.join('\n\n') - @buildEmptyLineHtml: (guideIndentation, showInvisibles, activeEditSession) -> + @buildHtmlEmptyLine: (guideIndentation, showInvisibles, activeEditSession) -> if guideIndentation > 0 - indentationHtml = "#{_.multiplyString(' ', @activeEditSession.getTabLength())}" - return _.multiplyString(indentationHtml, indentation) + indentationHtml = "#{_.multiplyString(' ', activeEditSession.getTabLength())}" + return _.multiplyString(indentationHtml, guideIndentation) else if not showInvisibles ' ' - buildEndOfLineInvisibles: (screenLine) -> - invisibles = [] - for invisible in @getEndOfLineInvisibles(screenLine) - invisibles.push("#{invisible}") - invisibles.join('') - - getEndOfLineInvisibles: (screenLine) -> - return [] unless @showInvisibles and @invisibles - return [] if @mini or screenLine.isSoftWrapped() - - buildLineHtml: (screenLine, screenRow) -> + buildHtmlFromLine: (screenLine, screenRow) -> { tokens, text, lineEnding, fold } = screenLine if fold attributes = { class: 'fold line', 'fold-id': fold.id } @@ -1368,7 +1358,10 @@ class Editor extends View break invisibles = @invisibles if @showInvisibles - Editor.buildLineHtmlHelper({tokens, text, lineEnding, fold, isSoftWrapped, invisibles, attributes, guideIndentation, @showInvisibles, @activeEditSession, @mini}) + Editor.buildHtmlHelper({tokens, text, lineEnding, fold, isSoftWrapped, invisibles, attributes, guideIndentation, @showInvisibles, @activeEditSession, @mini}) + + @buildHtmlLine: (tokens, text) -> + @buildHtmlHelper( {tokens, text} ) @buildHtmlHelper: ({tokens, text, lineEnding, fold, isSoftWrapped, invisibles, attributes, guideIndentation, showInvisibles, activeEditSession, mini}) => scopeStack = [] @@ -1399,8 +1392,11 @@ class Editor extends View attributePairs.push "#{attributeName}=\"#{value}\"" for attributeName, value of attributes line.push("
") + if showInvisibles + console.log invisibles + if text == '' - html = Editor.buildEmptyLineHtml(guideIndentation, showInvisibles, activeEditSession) + html = Editor.buildHtmlEmptyLine(guideIndentation, showInvisibles, activeEditSession) line.push(html) if html else firstNonWhitespacePosition = text.search(/\S/) @@ -1416,7 +1412,7 @@ class Editor extends View position += token.value.length popScope() while scopeStack.length > 0 - if invisibles and not @mini and not isSoftWrapped + if invisibles and not mini and not isSoftWrapped if invisibles.cr and lineEnding is '\r\n' line.push("#{invisibles.cr}") if invisibles.eol @@ -1568,6 +1564,73 @@ class Editor extends View logCursorScope: -> console.log @activeEditSession.getCursorScopes() + @buildLineHtml: ({tokens, text, lineEnding, fold, isSoftWrapped, invisibles, attributes, guideIndentation, showInvisibles, activeEditSession, mini}) => + scopeStack = [] + line = [] + + updateScopeStack = (desiredScopes) -> + excessScopes = scopeStack.length - desiredScopes.length + _.times(excessScopes, popScope) if excessScopes > 0 + + # pop until common prefix + for i in [scopeStack.length..0] + break if _.isEqual(scopeStack[0...i], desiredScopes[0...i]) + popScope() + + # push on top of common prefix until scopeStack == desiredScopes + for j in [i...desiredScopes.length] + pushScope(desiredScopes[j]) + + pushScope = (scope) -> + scopeStack.push(scope) + line.push("") + + popScope = -> + scopeStack.pop() + line.push("") + + attributePairs = [] + attributePairs.push "#{attributeName}=\"#{value}\"" for attributeName, value of attributes + line.push("
") + + if showInvisibles + console.log invisibles + + if text == '' + html = @buildEmptyLineHtml(guideIndentation, showInvisibles, activeEditSession) + line.push(html) if html + else + firstNonWhitespacePosition = text.search(/\S/) + firstTrailingWhitespacePosition = text.search(/\s*$/) + lineIsWhitespaceOnly = firstTrailingWhitespacePosition is 0 + position = 0 + for token in tokens + updateScopeStack(token.scopes) + hasLeadingWhitespace = position < firstNonWhitespacePosition + hasTrailingWhitespace = position + token.value.length > firstTrailingWhitespacePosition + hasIndentGuide = not @mini and guideIndentation? and (hasLeadingWhitespace or lineIsWhitespaceOnly) + line.push(token.getValueAsHtml({invisibles, hasLeadingWhitespace, hasTrailingWhitespace, hasIndentGuide})) + position += token.value.length + + popScope() while scopeStack.length > 0 + if invisibles and not mini and not isSoftWrapped + if invisibles.cr and lineEnding is '\r\n' + line.push("#{invisibles.cr}") + if invisibles.eol + line.push("#{invisibles.eol}") + + line.push("") if fold + + line.push('
') + line.join('') + + @buildEmptyLineHtml: (guideIndentation, showInvisibles, activeEditSession) -> + if guideIndentation > 0 + indentationHtml = "#{_.multiplyString(' ', activeEditSession.getTabLength())}" + return _.multiplyString(indentationHtml, guideIndentation) + else if not showInvisibles + ' ' + transact: (fn) -> @activeEditSession.transact(fn) commit: -> @activeEditSession.commit() abort: -> @activeEditSession.abort() diff --git a/src/packages/markdown-preview/lib/markdown-preview-view.coffee b/src/packages/markdown-preview/lib/markdown-preview-view.coffee index 6473a04f8..6f0c231e1 100644 --- a/src/packages/markdown-preview/lib/markdown-preview-view.coffee +++ b/src/packages/markdown-preview/lib/markdown-preview-view.coffee @@ -74,14 +74,10 @@ class MarkdownPreviewView extends ScrollView tokenizeCodeBlocks: (html) => html = $(html) preList = $(html.filter("pre")) - editorBackgroundColor = $('.editor').css("background-color") - rawEditorTextColor = $('.editor .gfm .raw').css("color") - for codeBlock in preList.toArray() - $(codeBlock).css("background-color", editorBackgroundColor) - codeBlock = $(codeBlock.firstChild) - # set the default raw color of unhiglighted pre tags - codeBlock.css("color", rawEditorTextColor) + for preElement in preList.toArray() + $(preElement).addClass("editor-colors") + codeBlock = $(preElement.firstChild) # go to next block unless this one has a class continue unless className = codeBlock.attr('class') @@ -90,22 +86,14 @@ class MarkdownPreviewView extends ScrollView # go to next block unless the class name is matches `lang` continue unless extension = fenceNameToExtension[fenceName] text = codeBlock.text() - syntax.selectGrammar("foo.#{extension}", text) # go to next block if this grammar is not mapped continue unless grammar = syntax.selectGrammar("foo.#{extension}", text) continue if grammar is syntax.nullGrammar - text = codeBlock.text() - tokens = grammar.tokenizeLines(text) - grouping = "" - for token in tokens - blockElem = $(Editor.buildHtmlLine(token, text)) - grouping += blockElem.addClass("editor")[0].outerHTML - - codeBlock.replaceWith(grouping) - # undo default coloring - codeBlock.css("color", "") + codeBlock.empty() + for tokens in grammar.tokenizeLines(text) + codeBlock.append(Editor.buildLineHtml({ tokens, text })) html diff --git a/src/packages/markdown-preview/stylesheets/markdown-preview.less b/src/packages/markdown-preview/stylesheets/markdown-preview.less index dd970afd8..4265e8cac 100644 --- a/src/packages/markdown-preview/stylesheets/markdown-preview.less +++ b/src/packages/markdown-preview/stylesheets/markdown-preview.less @@ -386,7 +386,6 @@ } .highlight pre, pre { - background-color: #f8f8f8; border: 1px solid #ccc; font-size: 13px; line-height: 19px;