256 lines
4.2 KiB
JavaScript
256 lines
4.2 KiB
JavaScript
'use strict'
|
|
|
|
var trim = require('trim-trailing-lines')
|
|
|
|
module.exports = fencedCode
|
|
|
|
var lineFeed = '\n'
|
|
var tab = '\t'
|
|
var space = ' '
|
|
var tilde = '~'
|
|
var graveAccent = '`'
|
|
|
|
var minFenceCount = 3
|
|
var tabSize = 4
|
|
|
|
function fencedCode(eat, value, silent) {
|
|
var self = this
|
|
var gfm = self.options.gfm
|
|
var length = value.length + 1
|
|
var index = 0
|
|
var subvalue = ''
|
|
var fenceCount
|
|
var marker
|
|
var character
|
|
var flag
|
|
var lang
|
|
var meta
|
|
var queue
|
|
var content
|
|
var exdentedContent
|
|
var closing
|
|
var exdentedClosing
|
|
var indent
|
|
var now
|
|
|
|
if (!gfm) {
|
|
return
|
|
}
|
|
|
|
// Eat initial spacing.
|
|
while (index < length) {
|
|
character = value.charAt(index)
|
|
|
|
if (character !== space && character !== tab) {
|
|
break
|
|
}
|
|
|
|
subvalue += character
|
|
index++
|
|
}
|
|
|
|
indent = index
|
|
|
|
// Eat the fence.
|
|
character = value.charAt(index)
|
|
|
|
if (character !== tilde && character !== graveAccent) {
|
|
return
|
|
}
|
|
|
|
index++
|
|
marker = character
|
|
fenceCount = 1
|
|
subvalue += character
|
|
|
|
while (index < length) {
|
|
character = value.charAt(index)
|
|
|
|
if (character !== marker) {
|
|
break
|
|
}
|
|
|
|
subvalue += character
|
|
fenceCount++
|
|
index++
|
|
}
|
|
|
|
if (fenceCount < minFenceCount) {
|
|
return
|
|
}
|
|
|
|
// Eat spacing before flag.
|
|
while (index < length) {
|
|
character = value.charAt(index)
|
|
|
|
if (character !== space && character !== tab) {
|
|
break
|
|
}
|
|
|
|
subvalue += character
|
|
index++
|
|
}
|
|
|
|
// Eat flag.
|
|
flag = ''
|
|
queue = ''
|
|
|
|
while (index < length) {
|
|
character = value.charAt(index)
|
|
|
|
if (
|
|
character === lineFeed ||
|
|
character === tilde ||
|
|
character === graveAccent
|
|
) {
|
|
break
|
|
}
|
|
|
|
if (character === space || character === tab) {
|
|
queue += character
|
|
} else {
|
|
flag += queue + character
|
|
queue = ''
|
|
}
|
|
|
|
index++
|
|
}
|
|
|
|
character = value.charAt(index)
|
|
|
|
if (character && character !== lineFeed) {
|
|
return
|
|
}
|
|
|
|
if (silent) {
|
|
return true
|
|
}
|
|
|
|
now = eat.now()
|
|
now.column += subvalue.length
|
|
now.offset += subvalue.length
|
|
|
|
subvalue += flag
|
|
flag = self.decode.raw(self.unescape(flag), now)
|
|
|
|
if (queue) {
|
|
subvalue += queue
|
|
}
|
|
|
|
queue = ''
|
|
closing = ''
|
|
exdentedClosing = ''
|
|
content = ''
|
|
exdentedContent = ''
|
|
|
|
// Eat content.
|
|
while (index < length) {
|
|
character = value.charAt(index)
|
|
content += closing
|
|
exdentedContent += exdentedClosing
|
|
closing = ''
|
|
exdentedClosing = ''
|
|
|
|
if (character !== lineFeed) {
|
|
content += character
|
|
exdentedClosing += character
|
|
index++
|
|
continue
|
|
}
|
|
|
|
// Add the newline to `subvalue` if its the first character. Otherwise,
|
|
// add it to the `closing` queue.
|
|
if (content) {
|
|
closing += character
|
|
exdentedClosing += character
|
|
} else {
|
|
subvalue += character
|
|
}
|
|
|
|
queue = ''
|
|
index++
|
|
|
|
while (index < length) {
|
|
character = value.charAt(index)
|
|
|
|
if (character !== space) {
|
|
break
|
|
}
|
|
|
|
queue += character
|
|
index++
|
|
}
|
|
|
|
closing += queue
|
|
exdentedClosing += queue.slice(indent)
|
|
|
|
if (queue.length >= tabSize) {
|
|
continue
|
|
}
|
|
|
|
queue = ''
|
|
|
|
while (index < length) {
|
|
character = value.charAt(index)
|
|
|
|
if (character !== marker) {
|
|
break
|
|
}
|
|
|
|
queue += character
|
|
index++
|
|
}
|
|
|
|
closing += queue
|
|
exdentedClosing += queue
|
|
|
|
if (queue.length < fenceCount) {
|
|
continue
|
|
}
|
|
|
|
queue = ''
|
|
|
|
while (index < length) {
|
|
character = value.charAt(index)
|
|
|
|
if (character !== space && character !== tab) {
|
|
break
|
|
}
|
|
|
|
closing += character
|
|
exdentedClosing += character
|
|
index++
|
|
}
|
|
|
|
if (!character || character === lineFeed) {
|
|
break
|
|
}
|
|
}
|
|
|
|
subvalue += content + closing
|
|
|
|
// Get lang and meta from the flag.
|
|
index = -1
|
|
length = flag.length
|
|
|
|
while (++index < length) {
|
|
character = flag.charAt(index)
|
|
|
|
if (character === space || character === tab) {
|
|
if (!lang) {
|
|
lang = flag.slice(0, index)
|
|
}
|
|
} else if (lang) {
|
|
meta = flag.slice(index)
|
|
break
|
|
}
|
|
}
|
|
|
|
return eat(subvalue)({
|
|
type: 'code',
|
|
lang: lang || flag || null,
|
|
meta: meta || null,
|
|
value: trim(exdentedContent)
|
|
})
|
|
}
|