{"version":3,"file":"smartquotes.mjs","sources":["../../../../../../node_modules/markdown-it/lib/rules_core/smartquotes.mjs"],"sourcesContent":["// Convert straight quotation marks to typographic ones\n//\n\nimport { isWhiteSpace, isPunctChar, isMdAsciiPunct } from '../common/utils.mjs'\n\nconst QUOTE_TEST_RE = /['\"]/\nconst QUOTE_RE = /['\"]/g\nconst APOSTROPHE = '\\u2019' /* ’ */\n\nfunction replaceAt (str, index, ch) {\n  return str.slice(0, index) + ch + str.slice(index + 1)\n}\n\nfunction process_inlines (tokens, state) {\n  let j\n\n  const stack = []\n\n  for (let i = 0; i < tokens.length; i++) {\n    const token = tokens[i]\n\n    const thisLevel = tokens[i].level\n\n    for (j = stack.length - 1; j >= 0; j--) {\n      if (stack[j].level <= thisLevel) { break }\n    }\n    stack.length = j + 1\n\n    if (token.type !== 'text') { continue }\n\n    let text = token.content\n    let pos = 0\n    let max = text.length\n\n    /* eslint no-labels:0,block-scoped-var:0 */\n    OUTER:\n    while (pos < max) {\n      QUOTE_RE.lastIndex = pos\n      const t = QUOTE_RE.exec(text)\n      if (!t) { break }\n\n      let canOpen = true\n      let canClose = true\n      pos = t.index + 1\n      const isSingle = (t[0] === \"'\")\n\n      // Find previous character,\n      // default to space if it's the beginning of the line\n      //\n      let lastChar = 0x20\n\n      if (t.index - 1 >= 0) {\n        lastChar = text.charCodeAt(t.index - 1)\n      } else {\n        for (j = i - 1; j >= 0; j--) {\n          if (tokens[j].type === 'softbreak' || tokens[j].type === 'hardbreak') break // lastChar defaults to 0x20\n          if (!tokens[j].content) continue // should skip all tokens except 'text', 'html_inline' or 'code_inline'\n\n          lastChar = tokens[j].content.charCodeAt(tokens[j].content.length - 1)\n          break\n        }\n      }\n\n      // Find next character,\n      // default to space if it's the end of the line\n      //\n      let nextChar = 0x20\n\n      if (pos < max) {\n        nextChar = text.charCodeAt(pos)\n      } else {\n        for (j = i + 1; j < tokens.length; j++) {\n          if (tokens[j].type === 'softbreak' || tokens[j].type === 'hardbreak') break // nextChar defaults to 0x20\n          if (!tokens[j].content) continue // should skip all tokens except 'text', 'html_inline' or 'code_inline'\n\n          nextChar = tokens[j].content.charCodeAt(0)\n          break\n        }\n      }\n\n      const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar))\n      const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar))\n\n      const isLastWhiteSpace = isWhiteSpace(lastChar)\n      const isNextWhiteSpace = isWhiteSpace(nextChar)\n\n      if (isNextWhiteSpace) {\n        canOpen = false\n      } else if (isNextPunctChar) {\n        if (!(isLastWhiteSpace || isLastPunctChar)) {\n          canOpen = false\n        }\n      }\n\n      if (isLastWhiteSpace) {\n        canClose = false\n      } else if (isLastPunctChar) {\n        if (!(isNextWhiteSpace || isNextPunctChar)) {\n          canClose = false\n        }\n      }\n\n      if (nextChar === 0x22 /* \" */ && t[0] === '\"') {\n        if (lastChar >= 0x30 /* 0 */ && lastChar <= 0x39 /* 9 */) {\n          // special case: 1\"\" - count first quote as an inch\n          canClose = canOpen = false\n        }\n      }\n\n      if (canOpen && canClose) {\n        // Replace quotes in the middle of punctuation sequence, but not\n        // in the middle of the words, i.e.:\n        //\n        // 1. foo \" bar \" baz - not replaced\n        // 2. foo-\"-bar-\"-baz - replaced\n        // 3. foo\"bar\"baz     - not replaced\n        //\n        canOpen = isLastPunctChar\n        canClose = isNextPunctChar\n      }\n\n      if (!canOpen && !canClose) {\n        // middle of word\n        if (isSingle) {\n          token.content = replaceAt(token.content, t.index, APOSTROPHE)\n        }\n        continue\n      }\n\n      if (canClose) {\n        // this could be a closing quote, rewind the stack to get a match\n        for (j = stack.length - 1; j >= 0; j--) {\n          let item = stack[j]\n          if (stack[j].level < thisLevel) { break }\n          if (item.single === isSingle && stack[j].level === thisLevel) {\n            item = stack[j]\n\n            let openQuote\n            let closeQuote\n            if (isSingle) {\n              openQuote = state.md.options.quotes[2]\n              closeQuote = state.md.options.quotes[3]\n            } else {\n              openQuote = state.md.options.quotes[0]\n              closeQuote = state.md.options.quotes[1]\n            }\n\n            // replace token.content *before* tokens[item.token].content,\n            // because, if they are pointing at the same token, replaceAt\n            // could mess up indices when quote length != 1\n            token.content = replaceAt(token.content, t.index, closeQuote)\n            tokens[item.token].content = replaceAt(\n              tokens[item.token].content, item.pos, openQuote)\n\n            pos += closeQuote.length - 1\n            if (item.token === i) { pos += openQuote.length - 1 }\n\n            text = token.content\n            max = text.length\n\n            stack.length = j\n            continue OUTER\n          }\n        }\n      }\n\n      if (canOpen) {\n        stack.push({\n          token: i,\n          pos: t.index,\n          single: isSingle,\n          level: thisLevel\n        })\n      } else if (canClose && isSingle) {\n        token.content = replaceAt(token.content, t.index, APOSTROPHE)\n      }\n    }\n  }\n}\n\nexport default function smartquotes (state) {\n  /* eslint max-depth:0 */\n  if (!state.md.options.typographer) { return }\n\n  for (let blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) {\n    if (state.tokens[blkIdx].type !== 'inline' ||\n        !QUOTE_TEST_RE.test(state.tokens[blkIdx].content)) {\n      continue\n    }\n\n    process_inlines(state.tokens[blkIdx].children, state)\n  }\n}\n"],"names":["QUOTE_TEST_RE","QUOTE_RE","APOSTROPHE","replaceAt","str","index","ch","process_inlines","tokens","state","j","stack","i","token","thisLevel","text","pos","max","OUTER","t","canOpen","canClose","isSingle","lastChar","nextChar","isLastPunctChar","isMdAsciiPunct","isPunctChar","isNextPunctChar","isLastWhiteSpace","isWhiteSpace","isNextWhiteSpace","item","openQuote","closeQuote","smartquotes","blkIdx"],"mappings":"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","x_google_ignoreList":[0]}