[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/vendor/s9e/text-formatter/src/Plugins/BBCodes/ -> Parser.js (source)

   1  /**
   2  * @type {!Object} Attributes of the BBCode being parsed
   3  */
   4  var attributes;
   5  
   6  /**
   7  * @type {!Object} Configuration for the BBCode being parsed
   8  */
   9  var bbcodeConfig;
  10  
  11  /**
  12  * @type {string} Name of the BBCode being parsed
  13  */
  14  var bbcodeName;
  15  
  16  /**
  17  * @type {string} Suffix of the BBCode being parsed, including its colon
  18  */
  19  var bbcodeSuffix;
  20  
  21  /**
  22  * @type {number} Position of the cursor in the original text
  23  */
  24  var pos;
  25  
  26  /**
  27  * @type {number} Position of the start of the BBCode being parsed
  28  */
  29  var startPos;
  30  
  31  /**
  32  * @type {number} Length of the text being parsed
  33  */
  34  var textLen = text.length;
  35  
  36  /**
  37  * @type {string} Text being parsed, normalized to uppercase
  38  */
  39  var uppercaseText = '';
  40  
  41  matches.forEach(function(m)
  42  {
  43      bbcodeName = m[1][0].toUpperCase();
  44      if (!(bbcodeName in config.bbcodes))
  45      {
  46          return;
  47      }
  48      bbcodeConfig = config.bbcodes[bbcodeName];
  49      startPos     = m[0][1];
  50      pos          = startPos + m[0][0].length;
  51  
  52      try
  53      {
  54          parseBBCode();
  55      }
  56      catch (e)
  57      {
  58          // Do nothing
  59      }
  60  });
  61  
  62  /**
  63  * Add the end tag that matches current BBCode
  64  *
  65  * @return {!Tag}
  66  */
  67  function addBBCodeEndTag()
  68  {
  69      return addEndTag(getTagName(), startPos, pos - startPos);
  70  }
  71  
  72  /**
  73  * Add the self-closing tag that matches current BBCode
  74  *
  75  * @return {!Tag}
  76  */
  77  function addBBCodeSelfClosingTag()
  78  {
  79      var tag = addSelfClosingTag(getTagName(), startPos, pos - startPos);
  80      tag.setAttributes(attributes);
  81  
  82      return tag;
  83  }
  84  
  85  /**
  86  * Add the start tag that matches current BBCode
  87  *
  88  * @return {!Tag}
  89  */
  90  function addBBCodeStartTag()
  91  {
  92      var prio = (bbcodeSuffix !== '') ? -10 : 0,
  93          tag = addStartTag(getTagName(), startPos, pos - startPos, prio);
  94      tag.setAttributes(attributes);
  95  
  96      return tag;
  97  }
  98  
  99  /**
 100  * Parse the end tag that matches given BBCode name and suffix starting at current position
 101  *
 102  * @return {?Tag}
 103  */
 104  function captureEndTag()
 105  {
 106      if (!uppercaseText)
 107      {
 108          uppercaseText = text.toUpperCase();
 109      }
 110      var match     = '[/' + bbcodeName + bbcodeSuffix + ']',
 111          endTagPos = uppercaseText.indexOf(match, pos);
 112      if (endTagPos < 0)
 113      {
 114          return null;
 115      }
 116  
 117      return addEndTag(getTagName(), endTagPos, match.length);
 118  }
 119  
 120  /**
 121  * Get the tag name for current BBCode
 122  *
 123  * @return {string}
 124  */
 125  function getTagName()
 126  {
 127      // Use the configured tagName if available, or reuse the BBCode's name otherwise
 128      return bbcodeConfig.tagName || bbcodeName;
 129  }
 130  
 131  /**
 132  * Parse attributes starting at current position
 133  */
 134  function parseAttributes()
 135  {
 136      var firstPos = pos, attrName;
 137      attributes = {};
 138      while (pos < textLen)
 139      {
 140          var c = text[pos];
 141          if (" \n\t".indexOf(c) > -1)
 142          {
 143              ++pos;
 144              continue;
 145          }
 146          if ('/]'.indexOf(c) > -1)
 147          {
 148              return;
 149          }
 150  
 151          // Capture the attribute name
 152          var spn = /^[-\w]*/.exec(text.substring(pos, pos + 100))[0].length;
 153          if (spn)
 154          {
 155              attrName = text.substring(pos, pos + spn).toLowerCase();
 156              pos += spn;
 157              if (pos >= textLen)
 158              {
 159                  // The attribute name extends to the end of the text
 160                  throw '';
 161              }
 162              if (text[pos] !== '=')
 163              {
 164                  // It's an attribute name not followed by an equal sign, ignore it
 165                  continue;
 166              }
 167          }
 168          else if (c === '=' && pos === firstPos)
 169          {
 170              // This is the default param, e.g. [quote=foo]
 171              attrName = bbcodeConfig.defaultAttribute || bbcodeName.toLowerCase();
 172          }
 173          else
 174          {
 175              throw '';
 176          }
 177  
 178          // Move past the = and make sure we're not at the end of the text
 179          if (++pos >= textLen)
 180          {
 181              throw '';
 182          }
 183  
 184          attributes[attrName] = parseAttributeValue();
 185      }
 186  }
 187  
 188  /**
 189  * Parse the attribute value starting at current position
 190  *
 191  * @return {string}
 192  */
 193  function parseAttributeValue()
 194  {
 195      // Test whether the value is in quotes
 196      if (text[pos] === '"' || text[pos] === "'")
 197      {
 198          return parseQuotedAttributeValue();
 199      }
 200  
 201      // Capture everything up to whichever comes first:
 202      //  - an endline
 203      //  - whitespace followed by a slash and a closing bracket
 204      //  - a closing bracket, optionally preceded by whitespace
 205      //  - whitespace followed by another attribute (name followed by equal sign)
 206      //
 207      // NOTE: this is for compatibility with some forums (such as vBulletin it seems)
 208      //       that do not put attribute values in quotes, e.g.
 209      //       [quote=John Smith;123456] (quoting "John Smith" from post #123456)
 210      var match     = /(?:[^\s\]]|[ \t](?!\s*(?:[-\w]+=|\/?\])))*/.exec(text.substring(pos)),
 211          attrValue = match[0];
 212      pos += attrValue.length;
 213  
 214      return attrValue;
 215  }
 216  
 217  /**
 218  * Parse current BBCode
 219  */
 220  function parseBBCode()
 221  {
 222      parseBBCodeSuffix();
 223  
 224      // Test whether this is an end tag
 225      if (text[startPos + 1] === '/')
 226      {
 227          // Test whether the tag is properly closed and whether this tag has an identifier.
 228          // We skip end tags that carry an identifier because they're automatically added
 229          // when their start tag is processed
 230          if (text[pos] === ']' && bbcodeSuffix === '')
 231          {
 232              ++pos;
 233              addBBCodeEndTag();
 234          }
 235  
 236          return;
 237      }
 238  
 239      // Parse attributes and fill in the blanks with predefined attributes
 240      parseAttributes();
 241      if (bbcodeConfig.predefinedAttributes)
 242      {
 243          for (var attrName in bbcodeConfig.predefinedAttributes)
 244          {
 245              if (!(attrName in attributes))
 246              {
 247                  attributes[attrName] = bbcodeConfig.predefinedAttributes[attrName];
 248              }
 249          }
 250      }
 251  
 252      // Test whether the tag is properly closed
 253      if (text[pos] === ']')
 254      {
 255          ++pos;
 256      }
 257      else
 258      {
 259          // Test whether this is a self-closing tag
 260          if (text.substring(pos, pos + 2) === '/]')
 261          {
 262              pos += 2;
 263              addBBCodeSelfClosingTag();
 264          }
 265  
 266          return;
 267      }
 268  
 269      // Record the names of attributes that need the content of this tag
 270      var contentAttributes = [];
 271      if (bbcodeConfig.contentAttributes)
 272      {
 273          bbcodeConfig.contentAttributes.forEach(function(attrName)
 274          {
 275              if (!(attrName in attributes))
 276              {
 277                  contentAttributes.push(attrName);
 278              }
 279          });
 280      }
 281  
 282      // Look ahead and parse the end tag that matches this tag, if applicable
 283      var requireEndTag = (bbcodeSuffix || bbcodeConfig.forceLookahead),
 284          endTag = (requireEndTag || contentAttributes.length) ? captureEndTag() : null;
 285      if (endTag)
 286      {
 287          contentAttributes.forEach(function(attrName)
 288          {
 289              attributes[attrName] = text.substring(pos, endTag.getPos());
 290          });
 291      }
 292      else if (requireEndTag)
 293      {
 294          return;
 295      }
 296  
 297      // Create this start tag
 298      var tag = addBBCodeStartTag();
 299  
 300      // If an end tag was created, pair it with this start tag
 301      if (endTag)
 302      {
 303          tag.pairWith(endTag);
 304      }
 305  }
 306  
 307  /**
 308  * Parse the BBCode suffix starting at current position
 309  *
 310  * Used to explicitly pair specific tags together, e.g.
 311  *   [code:123][code]type your code here[/code][/code:123]
 312  */
 313  function parseBBCodeSuffix()
 314  {
 315      bbcodeSuffix = '';
 316      if (text[pos] === ':')
 317      {
 318          // Capture the colon and the (0 or more) digits following it
 319          bbcodeSuffix = /^:\d*/.exec(text.substring(pos))[0];
 320  
 321          // Move past the suffix
 322          pos += bbcodeSuffix.length;
 323      }
 324  }
 325  
 326  /**
 327  * Parse a quoted attribute value that starts at current offset
 328  *
 329  * @return {string}
 330  */
 331  function parseQuotedAttributeValue()
 332  {
 333      var quote    = text[pos],
 334          valuePos = pos + 1;
 335      do
 336      {
 337          // Look for the next quote
 338          pos = text.indexOf(quote, pos + 1);
 339          if (pos < 0)
 340          {
 341              // No matching quote. Apparently that string never ends...
 342              throw '';
 343          }
 344  
 345          // Test for an odd number of backslashes before this character
 346          var n = 1;
 347          while (text[pos - n] === '\\')
 348          {
 349              ++n;
 350          }
 351      }
 352      while (n % 2 === 0);
 353  
 354      var attrValue = text.substring(valuePos, pos);
 355      if (attrValue.indexOf('\\') > -1)
 356      {
 357          attrValue = attrValue.replace(/\\([\\'"])/g, '$1');
 358      }
 359  
 360      // Skip past the closing quote
 361      ++pos;
 362  
 363      return attrValue;
 364  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1