diff --git a/lib/helpers/parse_image_size.js b/lib/helpers/parse_image_size.js new file mode 100644 index 0000000..1d20eef --- /dev/null +++ b/lib/helpers/parse_image_size.js @@ -0,0 +1,72 @@ +// Parse image size +// +'use strict'; + +function parseNextNumber(str, pos, max) { + var code, + start = pos, + result = { + ok: false, + pos: pos, + value: '' + }; + + code = str.charCodeAt(pos); + + while (pos < max && (code >= 0x30 /* 0 */ && code <= 0x39 /* 9 */)) { + code = str.charCodeAt(++pos); + } + + result.ok = true; + result.pos = pos; + result.value = str.slice(start, pos); + + return result; +} + +module.exports = function parseImageSize(str, pos, max) { + var code, + result = { + ok: false, + pos: 0, + width: '', + height: '' + }; + + if (pos >= max) { return result; } + + code = str.charCodeAt(pos); + + if (code !== 0x3d /* = */) { return result; } + + pos++; + + // size must follow = without any white spaces as follows + // (1) =300x200 + // (2) =300x + // (3) =x200 + code = str.charCodeAt(pos); + if (code !== 0x78 /* x */ && (code < 0x30 && code > 0x39) /* [0-9] */) { + return result; + } + + // parse width + var resultW = parseNextNumber(str, pos, max); + pos = resultW.pos; + + // next charactor must be 'x' + code = str.charCodeAt(pos); + if (code !== 0x78 /* x */) { return result; } + + pos++; + + // parse height + var resultH = parseNextNumber(str, pos, max); + pos = resultH.pos; + + result.width = resultW.value; + result.height = resultH.value; + result.pos = pos; + result.ok = true; + return result; +}; diff --git a/lib/parser_core.js b/lib/parser_core.js index 795ac67..7eb2f70 100644 --- a/lib/parser_core.js +++ b/lib/parser_core.js @@ -46,7 +46,6 @@ Core.prototype.process = function (state) { var i, l, rules; rules = this.ruler.getRules(''); - for (i = 0, l = rules.length; i < l; i++) { rules[i](state); } diff --git a/lib/renderer.js b/lib/renderer.js index 737e7dc..31dde8f 100644 --- a/lib/renderer.js +++ b/lib/renderer.js @@ -114,8 +114,11 @@ rules.image = function (tokens, idx, options, env, self) { var src = ' src="' + escapeHtml(tokens[idx].src) + '"'; var title = tokens[idx].title ? (' title="' + escapeHtml(replaceEntities(tokens[idx].title)) + '"') : ''; var alt = ' alt="' + self.renderInlineAsText(tokens[idx].tokens, options, env) + '"'; + var width = tokens[idx].width !== '' ? ' width="' + tokens[idx].width + '"' : ''; + var height = tokens[idx].height !== '' ? ' height="' + tokens[idx].height + '"' : ''; + var size = width + height; var suffix = options.xhtmlOut ? ' /' : ''; - return ''; + return ''; }; @@ -226,7 +229,6 @@ function Renderer() { Renderer.prototype.renderInline = function (tokens, options, env) { var result = '', _rules = this.rules; - for (var i = 0, len = tokens.length; i < len; i++) { result += _rules[tokens[i].type](tokens, i, options, env, this); } diff --git a/lib/rules_inline/image.js b/lib/rules_inline/image.js index 0a6a9bc..333cac1 100644 --- a/lib/rules_inline/image.js +++ b/lib/rules_inline/image.js @@ -6,7 +6,7 @@ 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'); - +var parseImageSize = require('../helpers/parse_image_size.js'); module.exports = function image(state, silent) { var code, @@ -18,6 +18,8 @@ module.exports = function image(state, silent) { ref, res, title, + width = '', + height = '', tokens, start, oldPos = state.pos, @@ -83,6 +85,30 @@ module.exports = function image(state, silent) { title = ''; } + // [link]( "title" =WxH ) + // ^^^^ parsing image size + if (pos - 1 >= 0) { + code = state.src.charCodeAt(pos - 1); + + // there must be at least one white spaces + // between previous field and the size + if (code === 0x20) { + res = parseImageSize(state.src, pos, state.posMax); + if (res.ok) { + width = res.width; + height = res.height; + pos = res.pos; + + // [link]( "title" =WxH ) + // ^^ skipping these spaces + for (; pos < max; pos++) { + code = state.src.charCodeAt(pos); + if (code !== 0x20 && code !== 0x0A) { break; } + } + } + } + } + if (pos >= max || state.src.charCodeAt(pos) !== 0x29/* ) */) { state.pos = oldPos; return false; @@ -147,7 +173,9 @@ module.exports = function image(state, silent) { src: href, title: title, tokens: tokens, - level: state.level + level: state.level, + width: width, + height: height }); } diff --git a/test/fixtures/markdown-it/commonmark_extras.txt b/test/fixtures/markdown-it/commonmark_extras.txt index 192b6a3..4181143 100644 --- a/test/fixtures/markdown-it/commonmark_extras.txt +++ b/test/fixtures/markdown-it/commonmark_extras.txt @@ -223,6 +223,31 @@ Coverage. Image .

![test](

. +. +![test]( x =100x200) +. +

test

+. +. +![test]( x =x) +. +

test

+. +. +![test]( x =100x) +. +

test

+. +. +![test]( x =x200) +. +

test

+. +. +![test]( x "title" =100x200) +. +

test

+. Coverage. Link