mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-11-13 08:44:12 +03:00
Merge pull request #507 from github/markdown-and-out
Swap out Markdown render logic with module
This commit is contained in:
commit
4b993b99cd
2
.pairs
2
.pairs
@ -6,7 +6,7 @@ pairs:
|
||||
jc: Jerry Cheung; jerry
|
||||
bl: Brian Lopez; brian
|
||||
jp: Justin Palmer; justin
|
||||
gt: Garen Torikian; garen
|
||||
email:
|
||||
domain: github.com
|
||||
#global: true
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
"plist": "git://github.com/nathansobo/node-plist.git",
|
||||
"space-pen": "git://github.com/nathansobo/space-pen.git",
|
||||
"less": "git://github.com/nathansobo/less.js.git",
|
||||
"roaster": "0.0.3",
|
||||
"jqueryui-browser": "1.10.2-1"
|
||||
},
|
||||
|
||||
|
19
spec/fixtures/markdown/file.markdown
vendored
19
spec/fixtures/markdown/file.markdown
vendored
@ -1,3 +1,20 @@
|
||||
## File.markdown
|
||||
|
||||
:cool:
|
||||
:cool:
|
||||
|
||||
```ruby
|
||||
def func
|
||||
x = 1
|
||||
end
|
||||
```
|
||||
|
||||
```
|
||||
function f(x) {
|
||||
return x++;
|
||||
}
|
||||
```
|
||||
|
||||
```kombucha
|
||||
drink-that-stuff:
|
||||
tastes-weird~
|
||||
```
|
||||
|
@ -94,7 +94,7 @@ class EditSession
|
||||
# Retrieves the filename of the open file.
|
||||
#
|
||||
# This is `'untitled'` if the file is new and not saved to the disk.
|
||||
#
|
||||
#
|
||||
# Returns a {String}.
|
||||
getTitle: ->
|
||||
if path = @getPath()
|
||||
@ -175,7 +175,7 @@ class EditSession
|
||||
setSoftWrap: (@softWrap) ->
|
||||
|
||||
# Retrieves that character used to indicate a tab.
|
||||
#
|
||||
#
|
||||
# If soft tabs are enabled, this is a space (`" "`) times the {.getTabLength} value.
|
||||
# Otherwise, it's a tab (`\t`).
|
||||
#
|
||||
@ -191,22 +191,22 @@ class EditSession
|
||||
#
|
||||
# tabLength - A {Number} that defines the new tab length.
|
||||
setTabLength: (tabLength) -> @displayBuffer.setTabLength(tabLength)
|
||||
|
||||
|
||||
# Given a position, this clips it to a real position.
|
||||
#
|
||||
# For example, if `position`'s row exceeds the row count of the buffer,
|
||||
# or if its column goes beyond a line's length, this "sanitizes" the value
|
||||
# or if its column goes beyond a line's length, this "sanitizes" the value
|
||||
# to a real position.
|
||||
#
|
||||
# position - The {Point} to clip
|
||||
#
|
||||
# Returns the new, clipped {Point}. Note that this could be the same as `position` if no clipping was performed.
|
||||
clipBufferPosition: (bufferPosition) -> @buffer.clipPosition(bufferPosition)
|
||||
|
||||
|
||||
# Given a range, this clips it to a real range.
|
||||
#
|
||||
# For example, if `range`'s row exceeds the row count of the buffer,
|
||||
# or if its column goes beyond a line's length, this "sanitizes" the value
|
||||
# or if its column goes beyond a line's length, this "sanitizes" the value
|
||||
# to a real range.
|
||||
#
|
||||
# range - The {Point} to clip
|
||||
@ -319,13 +319,13 @@ class EditSession
|
||||
|
||||
# {Delegates to: DisplayBuffer.screenPositionForBufferPosition}
|
||||
screenPositionForBufferPosition: (bufferPosition, options) -> @displayBuffer.screenPositionForBufferPosition(bufferPosition, options)
|
||||
|
||||
|
||||
# {Delegates to: DisplayBuffer.bufferPositionForScreenPosition}
|
||||
bufferPositionForScreenPosition: (screenPosition, options) -> @displayBuffer.bufferPositionForScreenPosition(screenPosition, options)
|
||||
|
||||
|
||||
# {Delegates to: DisplayBuffer.screenRangeForBufferRange}
|
||||
screenRangeForBufferRange: (bufferRange) -> @displayBuffer.screenRangeForBufferRange(bufferRange)
|
||||
|
||||
|
||||
# {Delegates to: DisplayBuffer.bufferRangeForScreenRange}
|
||||
bufferRangeForScreenRange: (screenRange) -> @displayBuffer.bufferRangeForScreenRange(screenRange)
|
||||
|
||||
@ -592,7 +592,7 @@ class EditSession
|
||||
|
||||
# Given a buffer row, this returns a suggested indentation level.
|
||||
#
|
||||
# The indentation level provided is based on the current language.
|
||||
# The indentation level provided is based on the current language.
|
||||
#
|
||||
# bufferRow - A {Number} indicating the buffer row
|
||||
#
|
||||
@ -806,7 +806,7 @@ class EditSession
|
||||
# {Delegates to: DisplayBuffer.getMarkerHeadScreenPosition}
|
||||
getMarkerHeadScreenPosition: (args...) ->
|
||||
@displayBuffer.getMarkerHeadScreenPosition(args...)
|
||||
|
||||
|
||||
# {Delegates to: DisplayBuffer.setMarkerHeadScreenPosition}
|
||||
setMarkerHeadScreenPosition: (args...) ->
|
||||
@displayBuffer.setMarkerHeadScreenPosition(args...)
|
||||
@ -826,7 +826,7 @@ class EditSession
|
||||
# {Delegates to: DisplayBuffer.setMarkerTailScreenPosition}
|
||||
setMarkerTailScreenPosition: (args...) ->
|
||||
@displayBuffer.setMarkerTailScreenPosition(args...)
|
||||
|
||||
|
||||
# {Delegates to: DisplayBuffer.getMarkerTailBufferPosition}
|
||||
getMarkerTailBufferPosition: (args...) ->
|
||||
@displayBuffer.getMarkerTailBufferPosition(args...)
|
||||
@ -990,7 +990,7 @@ class EditSession
|
||||
#
|
||||
# Returns an {Array} of {Selection}s.
|
||||
getSelections: -> new Array(@selections...)
|
||||
|
||||
|
||||
# Gets the selection at the specified index.
|
||||
#
|
||||
# index - The id {Number} of the selection
|
||||
@ -1268,7 +1268,7 @@ class EditSession
|
||||
# Selects all the text from the current cursor position to the beginning of the next word.
|
||||
selectToBeginningOfNextWord: ->
|
||||
@expandSelectionsForward (selection) => selection.selectToBeginningOfNextWord()
|
||||
|
||||
|
||||
# Selects the current word.
|
||||
selectWord: ->
|
||||
@expandSelectionsForward (selection) => selection.selectWord()
|
||||
|
@ -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,18 +1317,44 @@ class Editor extends View
|
||||
|
||||
buildLineElementsForScreenRows: (startRow, endRow) ->
|
||||
div = document.createElement('div')
|
||||
div.innerHTML = @buildLinesHtml(startRow, endRow)
|
||||
div.innerHTML = @htmlForScreenRows(startRow, endRow)
|
||||
new Array(div.children...)
|
||||
|
||||
buildLinesHtml: (startRow, endRow) ->
|
||||
htmlForScreenRows: (startRow, endRow) ->
|
||||
lines = @activeEditSession.linesForScreenRows(startRow, endRow)
|
||||
htmlLines = []
|
||||
screenRow = startRow
|
||||
for line in @activeEditSession.linesForScreenRows(startRow, endRow)
|
||||
htmlLines.push(@buildLineHtml(line, screenRow++))
|
||||
htmlLines.push(@htmlForScreenLine(line, screenRow++))
|
||||
htmlLines.join('\n\n')
|
||||
|
||||
buildEndOfLineInvisibles: (screenLine) ->
|
||||
htmlForScreenLine: (screenLine, screenRow) ->
|
||||
{ tokens, text, lineEnding, fold, isSoftWrapped } = screenLine
|
||||
if fold
|
||||
attributes = { class: 'fold line', 'fold-id': fold.id }
|
||||
else
|
||||
attributes = { class: 'line' }
|
||||
|
||||
invisibles = @invisibles if @showInvisibles
|
||||
eolInvisibles = @getEndOfLineInvisibles(screenLine)
|
||||
htmlEolInvisibles = @buildHtmlEndOfLineInvisibles(screenLine)
|
||||
|
||||
indentation = Editor.buildIndentation(screenRow, @activeEditSession)
|
||||
|
||||
Editor.buildLineHtml({tokens, text, lineEnding, fold, isSoftWrapped, invisibles, eolInvisibles, htmlEolInvisibles, attributes, @showIndentGuide, indentation, @activeEditSession, @mini})
|
||||
|
||||
@buildIndentation: (screenRow, activeEditSession) ->
|
||||
indentation = 0
|
||||
while --screenRow >= 0
|
||||
bufferRow = activeEditSession.bufferPositionForScreenPosition([screenRow]).row
|
||||
bufferLine = activeEditSession.lineForBufferRow(bufferRow)
|
||||
unless bufferLine is ''
|
||||
indentation = Math.ceil(activeEditSession.indentLevelForLine(bufferLine))
|
||||
break
|
||||
|
||||
indentation
|
||||
|
||||
buildHtmlEndOfLineInvisibles: (screenLine) ->
|
||||
invisibles = []
|
||||
for invisible in @getEndOfLineInvisibles(screenLine)
|
||||
invisibles.push("<span class='invisible-character'>#{invisible}</span>")
|
||||
@ -1343,99 +1369,6 @@ class Editor extends View
|
||||
invisibles.push(@invisibles.eol) if @invisibles.eol
|
||||
invisibles
|
||||
|
||||
buildEmptyLineHtml: (screenLine, screenRow) ->
|
||||
if not @mini and @showIndentGuide
|
||||
indentation = 0
|
||||
while --screenRow >= 0
|
||||
bufferRow = @activeEditSession.bufferPositionForScreenPosition([screenRow]).row
|
||||
bufferLine = @activeEditSession.lineForBufferRow(bufferRow)
|
||||
unless bufferLine is ''
|
||||
indentation = 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(''))
|
||||
|
||||
for invisible in invisibles
|
||||
indentGuideHtml.push("<span class='invisible-character'>#{invisible}</span>")
|
||||
return indentGuideHtml.join('')
|
||||
|
||||
invisibles = @buildEndOfLineInvisibles(screenLine)
|
||||
if invisibles.length > 0
|
||||
invisibles
|
||||
else
|
||||
' '
|
||||
|
||||
buildLineHtml: (screenLine, screenRow) ->
|
||||
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("<span class=\"#{scope.replace(/\./g, ' ')}\">")
|
||||
|
||||
popScope = ->
|
||||
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
|
||||
line.push("<div #{attributePairs.join(' ')}>")
|
||||
|
||||
invisibles = @invisibles if @showInvisibles
|
||||
|
||||
if screenLine.text == ''
|
||||
html = @buildEmptyLineHtml(screenLine, screenRow)
|
||||
line.push(html) if html
|
||||
else
|
||||
firstNonWhitespacePosition = screenLine.text.search(/\S/)
|
||||
firstTrailingWhitespacePosition = screenLine.text.search(/\s*$/)
|
||||
lineIsWhitespaceOnly = firstTrailingWhitespacePosition is 0
|
||||
position = 0
|
||||
for token in screenLine.tokens
|
||||
updateScopeStack(token.scopes)
|
||||
hasLeadingWhitespace = position < firstNonWhitespacePosition
|
||||
hasTrailingWhitespace = position + token.value.length > firstTrailingWhitespacePosition
|
||||
hasIndentGuide = not @mini and @showIndentGuide 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 == ''
|
||||
line.push("<span class='fold-marker'/>") if fold
|
||||
|
||||
line.push('</div>')
|
||||
line.join('')
|
||||
|
||||
lineElementForScreenRow: (screenRow) ->
|
||||
@renderedLines.children(":eq(#{screenRow - @firstRenderedScreenRow})")
|
||||
|
||||
@ -1460,7 +1393,7 @@ class Editor extends View
|
||||
#
|
||||
# Returns an object with two values: `top` and `left`, representing the pixel positions.
|
||||
pixelPositionForScreenPosition: (position) ->
|
||||
return { top: 0, left: 0 } unless @isOnDom() and @isVisible()
|
||||
return { top: 0, left: 0 } unless @isOnDom() and @isVisible()
|
||||
{row, column} = Point.fromObject(position)
|
||||
actualRow = Math.floor(row)
|
||||
|
||||
@ -1555,6 +1488,84 @@ class Editor extends View
|
||||
|
||||
### Internal ###
|
||||
|
||||
@buildLineHtml: ({tokens, text, lineEnding, fold, isSoftWrapped, invisibles, eolInvisibles, htmlEolInvisibles, attributes, showIndentGuide, indentation, 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("<span class=\"#{scope.replace(/\./g, ' ')}\">")
|
||||
|
||||
popScope = ->
|
||||
scopeStack.pop()
|
||||
line.push("</span>")
|
||||
|
||||
attributePairs = []
|
||||
attributePairs.push "#{attributeName}=\"#{value}\"" for attributeName, value of attributes
|
||||
line.push("<div #{attributePairs.join(' ')}>")
|
||||
|
||||
if text == ''
|
||||
html = Editor.buildEmptyLineHtml(showIndentGuide, eolInvisibles, htmlEolInvisibles, indentation, activeEditSession, mini)
|
||||
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 showIndentGuide and (hasLeadingWhitespace or lineIsWhitespaceOnly)
|
||||
line.push(token.getValueAsHtml({invisibles, hasLeadingWhitespace, hasTrailingWhitespace, hasIndentGuide}))
|
||||
position += token.value.length
|
||||
|
||||
popScope() while scopeStack.length > 0
|
||||
line.push(htmlEolInvisibles) unless text == ''
|
||||
line.push("<span class='fold-marker'/>") if fold
|
||||
|
||||
line.push('</div>')
|
||||
line.join('')
|
||||
|
||||
@buildEmptyLineHtml: (showIndentGuide, eolInvisibles, htmlEolInvisibles, indentation, activeEditSession, mini) ->
|
||||
if not mini and showIndentGuide
|
||||
if indentation > 0
|
||||
tabLength = activeEditSession.getTabLength()
|
||||
indentGuideHtml = []
|
||||
for level in [0...indentation]
|
||||
indentLevelHtml = ["<span class='indent-guide'>"]
|
||||
for characterPosition in [0...tabLength]
|
||||
if invisible = eolInvisibles.shift()
|
||||
indentLevelHtml.push("<span class='invisible-character'>#{invisible}</span>")
|
||||
else
|
||||
indentLevelHtml.push(' ')
|
||||
indentLevelHtml.push("</span>")
|
||||
indentGuideHtml.push(indentLevelHtml.join(''))
|
||||
|
||||
for invisible in eolInvisibles
|
||||
indentGuideHtml.push("<span class='invisible-character'>#{invisible}</span>")
|
||||
|
||||
return indentGuideHtml.join('')
|
||||
|
||||
invisibles = htmlEolInvisibles
|
||||
if invisibles.length > 0
|
||||
invisibles
|
||||
else
|
||||
' '
|
||||
|
||||
bindToKeyedEvent: (key, event, callback) ->
|
||||
binding = {}
|
||||
binding[key] = event
|
||||
|
@ -1,6 +1,17 @@
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
ScrollView = require 'scroll-view'
|
||||
{$$$} = require 'space-pen'
|
||||
roaster = require 'roaster'
|
||||
Editor = require 'editor'
|
||||
|
||||
fenceNameToExtension =
|
||||
"coffeescript": "coffee"
|
||||
"toml": "toml"
|
||||
"ruby": "rb"
|
||||
"go": "go"
|
||||
"mustache": "mustache"
|
||||
"java": "java"
|
||||
|
||||
module.exports =
|
||||
class MarkdownPreviewView extends ScrollView
|
||||
@ -15,13 +26,13 @@ class MarkdownPreviewView extends ScrollView
|
||||
initialize: (@buffer) ->
|
||||
super
|
||||
|
||||
@fetchRenderedMarkdown()
|
||||
@renderMarkdown()
|
||||
@on 'core:move-up', => @scrollUp()
|
||||
@on 'core:move-down', => @scrollDown()
|
||||
|
||||
afterAttach: (onDom) ->
|
||||
@subscribe @buffer, 'saved', =>
|
||||
@fetchRenderedMarkdown()
|
||||
@renderMarkdown()
|
||||
pane = @getPane()
|
||||
pane.showItem(this) if pane? and pane isnt rootView.getActivePane()
|
||||
|
||||
@ -42,7 +53,7 @@ class MarkdownPreviewView extends ScrollView
|
||||
@buffer.getPath()
|
||||
|
||||
setErrorHtml: (result)->
|
||||
try failureMessage = JSON.parse(result.responseText).message
|
||||
try failureMessage = JSON.parse(result).message
|
||||
|
||||
@html $$$ ->
|
||||
@h2 'Previewing Markdown Failed'
|
||||
@ -59,15 +70,38 @@ class MarkdownPreviewView extends ScrollView
|
||||
setLoading: ->
|
||||
@html($$$ -> @div class: 'markdown-spinner', 'Loading Markdown...')
|
||||
|
||||
fetchRenderedMarkdown: (text) ->
|
||||
|
||||
tokenizeCodeBlocks: (html) =>
|
||||
html = $(html)
|
||||
preList = $(html.filter("pre"))
|
||||
|
||||
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')
|
||||
|
||||
fenceName = className.replace(/^lang-/, '')
|
||||
# go to next block unless the class name is matches `lang`
|
||||
continue unless extension = fenceNameToExtension[fenceName]
|
||||
text = codeBlock.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
|
||||
|
||||
codeBlock.empty()
|
||||
for tokens in grammar.tokenizeLines(text)
|
||||
codeBlock.append(Editor.buildLineHtml({ tokens, text }))
|
||||
|
||||
html
|
||||
|
||||
renderMarkdown: ->
|
||||
@setLoading()
|
||||
$.ajax
|
||||
url: 'https://api.github.com/markdown'
|
||||
type: 'POST'
|
||||
dataType: 'html'
|
||||
contentType: 'application/json; charset=UTF-8'
|
||||
data: JSON.stringify
|
||||
mode: 'markdown'
|
||||
text: @buffer.getText()
|
||||
success: (html) => @html(html)
|
||||
error: (result) => @setErrorHtml(result)
|
||||
roaster(@buffer.getText(), {}, (err, html) =>
|
||||
if err
|
||||
@setErrorHtml(err)
|
||||
else
|
||||
@html(@tokenizeCodeBlocks(html))
|
||||
)
|
||||
|
@ -18,7 +18,7 @@ module.exports =
|
||||
{previewPane, previewItem} = @getExistingPreview(editSession)
|
||||
if previewItem?
|
||||
previewPane.showItem(previewItem)
|
||||
previewItem.fetchRenderedMarkdown()
|
||||
previewItem.renderMarkdown()
|
||||
else if nextPane = activePane.getNextPane()
|
||||
nextPane.showItem(new MarkdownPreviewView(editSession.buffer))
|
||||
else
|
||||
|
@ -8,7 +8,7 @@ describe "MarkdownPreview package", ->
|
||||
project.setPath(project.resolve('markdown'))
|
||||
window.rootView = new RootView
|
||||
atom.activatePackage("markdown-preview", immediate: true)
|
||||
spyOn(MarkdownPreviewView.prototype, 'fetchRenderedMarkdown')
|
||||
spyOn(MarkdownPreviewView.prototype, 'renderMarkdown')
|
||||
|
||||
describe "markdown-preview:show", ->
|
||||
beforeEach ->
|
||||
@ -61,9 +61,9 @@ describe "MarkdownPreview package", ->
|
||||
[pane] = rootView.getPanes()
|
||||
pane.focus()
|
||||
|
||||
MarkdownPreviewView.prototype.fetchRenderedMarkdown.reset()
|
||||
MarkdownPreviewView.prototype.renderMarkdown.reset()
|
||||
pane.activeItem.buffer.trigger 'saved'
|
||||
expect(MarkdownPreviewView.prototype.fetchRenderedMarkdown).not.toHaveBeenCalled()
|
||||
expect(MarkdownPreviewView.prototype.renderMarkdown).not.toHaveBeenCalled()
|
||||
|
||||
describe "when a preview item has already been created for the edit session's uri", ->
|
||||
it "updates and shows the existing preview item if it isn't displayed", ->
|
||||
@ -77,9 +77,9 @@ describe "MarkdownPreview package", ->
|
||||
expect(pane2.activeItem).not.toBe preview
|
||||
pane1.focus()
|
||||
|
||||
preview.fetchRenderedMarkdown.reset()
|
||||
preview.renderMarkdown.reset()
|
||||
rootView.getActiveView().trigger 'markdown-preview:show'
|
||||
expect(preview.fetchRenderedMarkdown).toHaveBeenCalled()
|
||||
expect(preview.renderMarkdown).toHaveBeenCalled()
|
||||
expect(rootView.getPanes()).toHaveLength 2
|
||||
expect(pane2.getItems()).toHaveLength 2
|
||||
expect(pane2.activeItem).toBe preview
|
||||
@ -95,9 +95,9 @@ describe "MarkdownPreview package", ->
|
||||
pane1.showItemAtIndex(0)
|
||||
preview = pane1.itemAtIndex(1)
|
||||
|
||||
preview.fetchRenderedMarkdown.reset()
|
||||
preview.renderMarkdown.reset()
|
||||
pane1.activeItem.buffer.trigger 'saved'
|
||||
expect(preview.fetchRenderedMarkdown).toHaveBeenCalled()
|
||||
expect(preview.renderMarkdown).toHaveBeenCalled()
|
||||
expect(pane1.activeItem).not.toBe preview
|
||||
|
||||
describe "when the preview is not in the same pane", ->
|
||||
@ -109,7 +109,7 @@ describe "MarkdownPreview package", ->
|
||||
expect(pane2.activeItem).not.toBe preview
|
||||
pane1.focus()
|
||||
|
||||
preview.fetchRenderedMarkdown.reset()
|
||||
preview.renderMarkdown.reset()
|
||||
pane1.activeItem.buffer.trigger 'saved'
|
||||
expect(preview.fetchRenderedMarkdown).toHaveBeenCalled()
|
||||
expect(preview.renderMarkdown).toHaveBeenCalled()
|
||||
expect(pane2.activeItem).toBe preview
|
||||
|
@ -6,34 +6,39 @@ describe "MarkdownPreviewView", ->
|
||||
[buffer, preview] = []
|
||||
|
||||
beforeEach ->
|
||||
spyOn($, 'ajax')
|
||||
project.setPath(project.resolve('markdown'))
|
||||
buffer = project.bufferForPath('file.markdown')
|
||||
atom.activatePackage('ruby.tmbundle', sync: true)
|
||||
preview = new MarkdownPreviewView(buffer)
|
||||
|
||||
afterEach ->
|
||||
buffer.release()
|
||||
|
||||
describe "on construction", ->
|
||||
ajaxArgs = null
|
||||
|
||||
beforeEach ->
|
||||
ajaxArgs = $.ajax.argsForCall[0][0]
|
||||
|
||||
it "shows a loading spinner and fetches the rendered markdown", ->
|
||||
it "shows a loading spinner and renders the markdown", ->
|
||||
preview.setLoading()
|
||||
expect(preview.find('.markdown-spinner')).toExist()
|
||||
expect($.ajax).toHaveBeenCalled()
|
||||
expect(preview.buffer.getText()).toBe buffer.getText()
|
||||
|
||||
expect(JSON.parse(ajaxArgs.data).text).toBe buffer.getText()
|
||||
|
||||
ajaxArgs.success($$$ -> @div "WWII", class: 'private-ryan')
|
||||
expect(preview.find(".private-ryan")).toExist()
|
||||
preview.renderMarkdown()
|
||||
expect(preview.find(".emoji")).toExist()
|
||||
|
||||
it "shows an error message on error", ->
|
||||
ajaxArgs.error()
|
||||
preview.setErrorHtml("Not a real file")
|
||||
expect(preview.text()).toContain "Failed"
|
||||
|
||||
describe "serialization", ->
|
||||
it "reassociates with the same buffer when deserialized", ->
|
||||
newPreview = deserialize(preview.serialize())
|
||||
expect(newPreview.buffer).toBe buffer
|
||||
|
||||
describe "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 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", ->
|
||||
expect(preview.find("pre code:not([class])").children().length).toBe 0
|
||||
expect(preview.find("pre code.lang-kombucha").children().length).toBe 0
|
||||
|
@ -23,6 +23,7 @@
|
||||
// includes some GitHub Flavored Markdown specific styling (like @mentions)
|
||||
.markdown-preview {
|
||||
pre,
|
||||
pre div.editor,
|
||||
code,
|
||||
tt {
|
||||
font-size: 12px;
|
||||
@ -385,7 +386,6 @@
|
||||
}
|
||||
|
||||
.highlight pre, pre {
|
||||
background-color: #f8f8f8;
|
||||
border: 1px solid #ccc;
|
||||
font-size: 13px;
|
||||
line-height: 19px;
|
||||
@ -400,4 +400,9 @@
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.emoji {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
.editor, .editor .gutter {
|
||||
.editor-colors {
|
||||
background-color: #1d1f21;
|
||||
color: #c5c8c6;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user