254 lines
4.1 KiB
JavaScript
254 lines
4.1 KiB
JavaScript
'use strict'
|
||
|
||
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 ||
|
||
(marker === graveAccent && character === marker)
|
||
) {
|
||
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 = ''
|
||
var skip = true
|
||
|
||
// Eat content.
|
||
while (index < length) {
|
||
character = value.charAt(index)
|
||
content += closing
|
||
exdentedContent += exdentedClosing
|
||
closing = ''
|
||
exdentedClosing = ''
|
||
|
||
if (character !== lineFeed) {
|
||
content += character
|
||
exdentedClosing += character
|
||
index++
|
||
continue
|
||
}
|
||
|
||
// The first line feed is ignored. Others aren’t.
|
||
if (skip) {
|
||
subvalue += character
|
||
skip = false
|
||
} else {
|
||
closing += character
|
||
exdentedClosing += 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: exdentedContent
|
||
})
|
||
}
|