mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-21 07:58:04 +03:00
Implement highlighting of Markdown pre blocks
This commit is contained in:
parent
dd041945d2
commit
cf239ccac0
@ -1342,42 +1342,24 @@ class Editor extends View
|
||||
invisibles.push(@invisibles.cr) if @invisibles.cr and screenLine.lineEnding is '\r\n'
|
||||
invisibles.push(@invisibles.eol) if @invisibles.eol
|
||||
invisibles
|
||||
|
||||
buildEmptyLineHtml: (screenLine, screenRow) ->
|
||||
|
||||
buildEmptyLineHtml: (screenRow) ->
|
||||
if not @mini and @showIndentGuide
|
||||
indentation = 0
|
||||
guideIndentation = 0
|
||||
while --screenRow >= 0
|
||||
bufferRow = @activeEditSession.bufferPositionForScreenPosition([screenRow]).row
|
||||
bufferLine = @activeEditSession.lineForBufferRow(bufferRow)
|
||||
unless bufferLine is ''
|
||||
indentation = Math.ceil(@activeEditSession.indentLevelForLine(bufferLine))
|
||||
guideIndentation = Math.ceil(@activeEditSession.indentLevelForLine(bufferLine))
|
||||
break
|
||||
|
||||
if indentation > 0
|
||||
tabLength = @activeEditSession.getTabLength()
|
||||
invisibles = @getEndOfLineInvisibles(screenLine)
|
||||
indentGuideHtml = []
|
||||
for level in [0...indentation]
|
||||
indentLevelHtml = ["<span class='indent-guide'>"]
|
||||
for characterPosition in [0...tabLength]
|
||||
if invisible = invisibles.shift()
|
||||
indentLevelHtml.push("<span class='invisible-character'>#{invisible}</span>")
|
||||
else
|
||||
indentLevelHtml.push(' ')
|
||||
indentLevelHtml.push("</span>")
|
||||
indentGuideHtml.push(indentLevelHtml.join(''))
|
||||
indentationHtml = "<span class='indent-guide'>#{_.multiplyString(' ', @activeEditSession.getTabLength())}</span>"
|
||||
return _.multiplyString(indentationHtml, indentation)
|
||||
|
||||
for invisible in invisibles
|
||||
indentGuideHtml.push("<span class='invisible-character'>#{invisible}</span>")
|
||||
return indentGuideHtml.join('')
|
||||
return ' ' unless @showInvisibles
|
||||
|
||||
invisibles = @buildEndOfLineInvisibles(screenLine)
|
||||
if invisibles.length > 0
|
||||
invisibles
|
||||
else
|
||||
' '
|
||||
|
||||
buildLineHtml: (screenLine, screenRow) ->
|
||||
@buildLineHtmlHelper: ({tokens, text, lineEnding, fold, isSoftWrapped, attributes, guideIndentation, showInvisibles}) ->
|
||||
scopeStack = []
|
||||
line = []
|
||||
|
||||
@ -1402,35 +1384,35 @@ class Editor extends View
|
||||
scopeStack.pop()
|
||||
line.push("</span>")
|
||||
|
||||
if fold = screenLine.fold
|
||||
lineAttributes = { class: 'fold line', 'fold-id': fold.id }
|
||||
else
|
||||
lineAttributes = { class: 'line' }
|
||||
|
||||
attributePairs = []
|
||||
attributePairs.push "#{attributeName}=\"#{value}\"" for attributeName, value of lineAttributes
|
||||
attributePairs.push "#{attributeName}=\"#{value}\"" for attributeName, value of attributes
|
||||
line.push("<div #{attributePairs.join(' ')}>")
|
||||
|
||||
invisibles = @invisibles if @showInvisibles
|
||||
invisibles = @invisibles if showInvisibles
|
||||
|
||||
if screenLine.text == ''
|
||||
html = @buildEmptyLineHtml(screenLine, screenRow)
|
||||
html = @buildEmptyLineHtml(screenRow)
|
||||
line.push(html) if html
|
||||
else
|
||||
firstNonWhitespacePosition = screenLine.text.search(/\S/)
|
||||
firstTrailingWhitespacePosition = screenLine.text.search(/\s*$/)
|
||||
firstNonWhitespacePosition = text.search(/\S/)
|
||||
firstTrailingWhitespacePosition = text.search(/\s*$/)
|
||||
lineIsWhitespaceOnly = firstTrailingWhitespacePosition is 0
|
||||
position = 0
|
||||
for token in screenLine.tokens
|
||||
for token in tokens
|
||||
updateScopeStack(token.scopes)
|
||||
hasLeadingWhitespace = position < firstNonWhitespacePosition
|
||||
hasTrailingWhitespace = position + token.value.length > firstTrailingWhitespacePosition
|
||||
hasIndentGuide = not @mini and @showIndentGuide and (hasLeadingWhitespace or lineIsWhitespaceOnly)
|
||||
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
|
||||
line.push(@buildEndOfLineInvisibles(screenLine)) unless screenLine.text == ''
|
||||
if invisibles and not @mini and not screenLine.isSoftWrapped()
|
||||
if invisibles.cr and screenLine.lineEnding is '\r\n'
|
||||
line.push("<span class='invisible-character'>#{invisibles.cr}</span>")
|
||||
if invisibles.eol
|
||||
line.push("<span class='invisible-character'>#{invisibles.eol}</span>")
|
||||
|
||||
line.push("<span class='fold-marker'/>") if fold
|
||||
|
||||
line.push('</div>')
|
||||
|
@ -3,8 +3,10 @@ _ = require 'underscore'
|
||||
ScrollView = require 'scroll-view'
|
||||
{$$$} = require 'space-pen'
|
||||
roaster = require 'roaster'
|
||||
LanguageMode = require 'language-mode'
|
||||
Buffer = require 'text-buffer'
|
||||
Editor = require 'editor'
|
||||
|
||||
fenceNameToExtension =
|
||||
"ruby": "rb"
|
||||
|
||||
module.exports =
|
||||
class MarkdownPreviewView extends ScrollView
|
||||
@ -63,27 +65,32 @@ class MarkdownPreviewView extends ScrollView
|
||||
setLoading: ->
|
||||
@html($$$ -> @div class: 'markdown-spinner', 'Loading Markdown...')
|
||||
|
||||
tokenizeCodeBlocks: (html) =>
|
||||
html = $(html)
|
||||
preList = $(html.filter("pre"))
|
||||
|
||||
for codeBlock in preList.toArray()
|
||||
codeBlock = $(codeBlock.firstChild)
|
||||
if className = codeBlock.attr('class')
|
||||
fenceName = className.replace(/^lang-/, '')
|
||||
|
||||
if extension = fenceNameToExtension[fenceName]
|
||||
text = codeBlock.text()
|
||||
syntax.selectGrammar("foo.#{extension}", text)
|
||||
if grammar = syntax.selectGrammar("foo.#{extension}", text)
|
||||
continue if grammar is syntax.nullGrammar
|
||||
tokens = grammar.tokenizeLines(text)
|
||||
grouping = ""
|
||||
for token in tokens
|
||||
grouping += Editor.buildLineHtml(token, text)
|
||||
codeBlock.replaceWith(grouping)
|
||||
html
|
||||
|
||||
fetchRenderedMarkdown: ->
|
||||
@setLoading()
|
||||
roaster(@buffer.getText(), {}, (err, html) =>
|
||||
if err
|
||||
@setErrorHtml(err)
|
||||
else
|
||||
result = @html(html)
|
||||
preList = result.find("pre")
|
||||
for pre in preList
|
||||
grammar = _.find syntax.grammars, (grammar) ->
|
||||
return "ruby" == grammar.scopeName.split(".").pop()
|
||||
|
||||
if grammar
|
||||
languageMode = new LanguageMode(this, grammar)
|
||||
console.log pre
|
||||
code = pre.childNodes[0]
|
||||
text = code.textContent.split("\n")
|
||||
|
||||
for line in text
|
||||
tokens = languageMode.tokenizeLine(text)
|
||||
console.log tokens
|
||||
#codeBuffer = new Buffer("", text)
|
||||
#x = 1
|
||||
@html(@tokenizeCodeBlocks(html))
|
||||
)
|
||||
|
@ -8,6 +8,7 @@ describe "MarkdownPreviewView", ->
|
||||
beforeEach ->
|
||||
project.setPath(project.resolve('markdown'))
|
||||
buffer = project.bufferForPath('file.markdown')
|
||||
atom.activatePackage('ruby.tmbundle', sync: true)
|
||||
preview = new MarkdownPreviewView(buffer)
|
||||
|
||||
afterEach ->
|
||||
@ -35,7 +36,7 @@ describe "MarkdownPreviewView", ->
|
||||
fdescribe "code block tokenization", ->
|
||||
describe "when the code block's fence name has a matching grammar", ->
|
||||
it "tokenizes the code block with the grammar", ->
|
||||
expect(preview.find("pre code.lang-ruby .entity.name.function.ruby")).toExist()
|
||||
expect(preview.find("pre span.entity.name.function.ruby")).toExist()
|
||||
|
||||
describe "when the code block's fence name doesn't have a matching grammar", ->
|
||||
it "does not tokenize the code block", ->
|
||||
|
Loading…
Reference in New Issue
Block a user