Alex Kocharin
10 years ago
5 changed files with 175 additions and 44 deletions
@ -0,0 +1,154 @@ |
|||||
|
// Process ![image](<src> "title")
|
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
var parseLinkLabel = require('../helpers/parse_link_label'); |
||||
|
var parseLinkDestination = require('../helpers/parse_link_destination'); |
||||
|
var parseLinkTitle = require('../helpers/parse_link_title'); |
||||
|
var normalizeReference = require('../helpers/normalize_reference'); |
||||
|
|
||||
|
|
||||
|
module.exports = function image(state, silent) { |
||||
|
var code, |
||||
|
href, |
||||
|
label, |
||||
|
labelEnd, |
||||
|
labelStart, |
||||
|
pos, |
||||
|
ref, |
||||
|
title, |
||||
|
tokens, |
||||
|
start, |
||||
|
oldPos = state.pos, |
||||
|
max = state.posMax; |
||||
|
|
||||
|
if (state.src.charCodeAt(state.pos) !== 0x21/* ! */) { return false; } |
||||
|
if (state.src.charCodeAt(state.pos + 1) !== 0x5B/* [ */) { return false; } |
||||
|
|
||||
|
labelStart = state.pos + 2; |
||||
|
labelEnd = parseLinkLabel(state, state.pos + 1, false); |
||||
|
|
||||
|
// parser failed to find ']', so it's not a valid link
|
||||
|
if (labelEnd < 0) { return false; } |
||||
|
|
||||
|
pos = labelEnd + 1; |
||||
|
if (pos < max && state.src.charCodeAt(pos) === 0x28/* ( */) { |
||||
|
//
|
||||
|
// Inline link
|
||||
|
//
|
||||
|
|
||||
|
// [link]( <href> "title" )
|
||||
|
// ^^ skipping these spaces
|
||||
|
pos++; |
||||
|
for (; pos < max; pos++) { |
||||
|
code = state.src.charCodeAt(pos); |
||||
|
if (code !== 0x20 && code !== 0x0A) { break; } |
||||
|
} |
||||
|
if (pos >= max) { return false; } |
||||
|
|
||||
|
// [link]( <href> "title" )
|
||||
|
// ^^^^^^ parsing link destination
|
||||
|
start = pos; |
||||
|
if (parseLinkDestination(state, pos)) { |
||||
|
href = state.linkContent; |
||||
|
pos = state.pos; |
||||
|
} else { |
||||
|
href = ''; |
||||
|
} |
||||
|
|
||||
|
// [link]( <href> "title" )
|
||||
|
// ^^ skipping these spaces
|
||||
|
start = pos; |
||||
|
for (; pos < max; pos++) { |
||||
|
code = state.src.charCodeAt(pos); |
||||
|
if (code !== 0x20 && code !== 0x0A) { break; } |
||||
|
} |
||||
|
|
||||
|
// [link]( <href> "title" )
|
||||
|
// ^^^^^^^ parsing link title
|
||||
|
if (pos < max && start !== pos && parseLinkTitle(state, pos)) { |
||||
|
title = state.linkContent; |
||||
|
pos = state.pos; |
||||
|
|
||||
|
// [link]( <href> "title" )
|
||||
|
// ^^ skipping these spaces
|
||||
|
for (; pos < max; pos++) { |
||||
|
code = state.src.charCodeAt(pos); |
||||
|
if (code !== 0x20 && code !== 0x0A) { break; } |
||||
|
} |
||||
|
} else { |
||||
|
title = ''; |
||||
|
} |
||||
|
|
||||
|
if (pos >= max || state.src.charCodeAt(pos) !== 0x29/* ) */) { |
||||
|
state.pos = oldPos; |
||||
|
return false; |
||||
|
} |
||||
|
pos++; |
||||
|
} else { |
||||
|
//
|
||||
|
// Link reference
|
||||
|
//
|
||||
|
if (typeof state.env.references === 'undefined') { return false; } |
||||
|
|
||||
|
// [foo] [bar]
|
||||
|
// ^^ optional whitespace (can include newlines)
|
||||
|
for (; pos < max; pos++) { |
||||
|
code = state.src.charCodeAt(pos); |
||||
|
if (code !== 0x20 && code !== 0x0A) { break; } |
||||
|
} |
||||
|
|
||||
|
if (pos < max && state.src.charCodeAt(pos) === 0x5B/* [ */) { |
||||
|
start = pos + 1; |
||||
|
pos = parseLinkLabel(state, pos); |
||||
|
if (pos >= 0) { |
||||
|
label = state.src.slice(start, pos++); |
||||
|
} else { |
||||
|
pos = labelEnd + 1; |
||||
|
} |
||||
|
} else { |
||||
|
pos = labelEnd + 1; |
||||
|
} |
||||
|
|
||||
|
// covers label === '' and label === undefined
|
||||
|
// (collapsed reference link and shortcut reference link respectively)
|
||||
|
if (!label) { label = state.src.slice(labelStart, labelEnd); } |
||||
|
|
||||
|
ref = state.env.references[normalizeReference(label)]; |
||||
|
if (!ref) { |
||||
|
state.pos = oldPos; |
||||
|
return false; |
||||
|
} |
||||
|
href = ref.href; |
||||
|
title = ref.title; |
||||
|
} |
||||
|
|
||||
|
//
|
||||
|
// We found the end of the link, and know for a fact it's a valid link;
|
||||
|
// so all that's left to do is to call tokenizer.
|
||||
|
//
|
||||
|
if (!silent) { |
||||
|
state.pos = labelStart; |
||||
|
state.posMax = labelEnd; |
||||
|
|
||||
|
var newState = new state.md.inline.State( |
||||
|
state.src.slice(labelStart, labelEnd), |
||||
|
state.md, |
||||
|
state.env, |
||||
|
tokens = [] |
||||
|
); |
||||
|
newState.md.inline.tokenize(newState); |
||||
|
|
||||
|
state.push({ |
||||
|
type: 'image', |
||||
|
src: href, |
||||
|
title: title, |
||||
|
tokens: tokens, |
||||
|
level: state.level |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
state.pos = pos; |
||||
|
state.posMax = max; |
||||
|
return true; |
||||
|
}; |
Loading…
Reference in new issue