| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 | // Adapted from markdown-it-imsize plugin by @tatsy// Original source https://github.com/tatsy/markdown-it-imsize/blob/master/lib/index.jsfunction renderImSize (state, silent) {  let attrs  let code  let label  let pos  let ref  let res  let title  let width = ''  let height = ''  let token  let tokens  let start  let href = ''  const oldPos = state.pos  const max = state.posMax  if (state.src.charCodeAt(state.pos) !== 0x21/* ! */) { return false }  if (state.src.charCodeAt(state.pos + 1) !== 0x5B/* [ */) { return false }  const labelStart = state.pos + 2  const labelEnd = state.md.helpers.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    res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax)    if (res.ok) {      href = state.md.normalizeLink(res.str)      if (state.md.validateLink(href)) {        pos = res.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    res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax)    if (pos < max && start !== pos && res.ok) {      title = res.str      pos = res.pos      // [link](  <href>  "title"  )      //                         ^^ skipping these spaces      for (; pos < max; pos++) {        code = state.src.charCodeAt(pos)        if (code !== 0x20 && code !== 0x0A) { break }      }    } else {      title = ''    }    // [link](  <href>  "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](  <href>  "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    }    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 = state.md.helpers.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[state.md.utils.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    const newState = new state.md.inline.State(      state.src.slice(labelStart, labelEnd),      state.md,      state.env,      tokens = []    )    newState.md.inline.tokenize(newState)    token = state.push('image', 'img', 0)    token.attrs = attrs = [['src', href],      ['alt', '']]    token.children = tokens    if (title) {      attrs.push(['title', title])    }    if (width !== '') {      attrs.push(['width', width])    }    if (height !== '') {      attrs.push(['height', height])    }  }  state.pos = pos  state.posMax = max  return true}function parseNextNumber (str, pos, max) {  let code  const start = pos  const result = {    ok: false,    pos,    value: ''  }  code = str.charCodeAt(pos)  while ((pos < max && (code >= 0x30 /* 0 */ && code <= 0x39 /* 9 */)) || code === 0x25 /* % */) {    code = str.charCodeAt(++pos)  }  result.ok = true  result.pos = pos  result.value = str.slice(start, pos)  return result}function parseImageSize (str, pos, max) {  let code  const 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  const 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  const resultH = parseNextNumber(str, pos, max)  pos = resultH.pos  result.width = resultW.value  result.height = resultH.value  result.pos = pos  result.ok = true  return result}export default (md) => {  md.inline.ruler.before('emphasis', 'image', renderImSize)}
 |