288 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			288 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/**
 | 
						|
 * @param {string} value
 | 
						|
 * @returns {RegExp}
 | 
						|
 * */
 | 
						|
 | 
						|
/**
 | 
						|
 * @param {RegExp | string } re
 | 
						|
 * @returns {string}
 | 
						|
 */
 | 
						|
function source(re) {
 | 
						|
  if (!re) return null;
 | 
						|
  if (typeof re === "string") return re;
 | 
						|
 | 
						|
  return re.source;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @param {RegExp | string } re
 | 
						|
 * @returns {string}
 | 
						|
 */
 | 
						|
function lookahead(re) {
 | 
						|
  return concat('(?=', re, ')');
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @param {RegExp | string } re
 | 
						|
 * @returns {string}
 | 
						|
 */
 | 
						|
function optional(re) {
 | 
						|
  return concat('(', re, ')?');
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @param {...(RegExp | string) } args
 | 
						|
 * @returns {string}
 | 
						|
 */
 | 
						|
function concat(...args) {
 | 
						|
  const joined = args.map((x) => source(x)).join("");
 | 
						|
  return joined;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Any of the passed expresssions may match
 | 
						|
 *
 | 
						|
 * Creates a huge this | this | that | that match
 | 
						|
 * @param {(RegExp | string)[] } args
 | 
						|
 * @returns {string}
 | 
						|
 */
 | 
						|
function either(...args) {
 | 
						|
  const joined = '(' + args.map((x) => source(x)).join("|") + ")";
 | 
						|
  return joined;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
Language: HTML, XML
 | 
						|
Website: https://www.w3.org/XML/
 | 
						|
Category: common
 | 
						|
Audit: 2020
 | 
						|
*/
 | 
						|
 | 
						|
/** @type LanguageFn */
 | 
						|
function xml(hljs) {
 | 
						|
  // Element names can contain letters, digits, hyphens, underscores, and periods
 | 
						|
  const TAG_NAME_RE = concat(/[A-Z_]/, optional(/[A-Z0-9_.-]*:/), /[A-Z0-9_.-]*/);
 | 
						|
  const XML_IDENT_RE = /[A-Za-z0-9._:-]+/;
 | 
						|
  const XML_ENTITIES = {
 | 
						|
    className: 'symbol',
 | 
						|
    begin: /&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/
 | 
						|
  };
 | 
						|
  const XML_META_KEYWORDS = {
 | 
						|
    begin: /\s/,
 | 
						|
    contains: [
 | 
						|
      {
 | 
						|
        className: 'meta-keyword',
 | 
						|
        begin: /#?[a-z_][a-z1-9_-]+/,
 | 
						|
        illegal: /\n/
 | 
						|
      }
 | 
						|
    ]
 | 
						|
  };
 | 
						|
  const XML_META_PAR_KEYWORDS = hljs.inherit(XML_META_KEYWORDS, {
 | 
						|
    begin: /\(/,
 | 
						|
    end: /\)/
 | 
						|
  });
 | 
						|
  const APOS_META_STRING_MODE = hljs.inherit(hljs.APOS_STRING_MODE, {
 | 
						|
    className: 'meta-string'
 | 
						|
  });
 | 
						|
  const QUOTE_META_STRING_MODE = hljs.inherit(hljs.QUOTE_STRING_MODE, {
 | 
						|
    className: 'meta-string'
 | 
						|
  });
 | 
						|
  const TAG_INTERNALS = {
 | 
						|
    endsWithParent: true,
 | 
						|
    illegal: /</,
 | 
						|
    relevance: 0,
 | 
						|
    contains: [
 | 
						|
      {
 | 
						|
        className: 'attr',
 | 
						|
        begin: XML_IDENT_RE,
 | 
						|
        relevance: 0
 | 
						|
      },
 | 
						|
      {
 | 
						|
        begin: /=\s*/,
 | 
						|
        relevance: 0,
 | 
						|
        contains: [
 | 
						|
          {
 | 
						|
            className: 'string',
 | 
						|
            endsParent: true,
 | 
						|
            variants: [
 | 
						|
              {
 | 
						|
                begin: /"/,
 | 
						|
                end: /"/,
 | 
						|
                contains: [ XML_ENTITIES ]
 | 
						|
              },
 | 
						|
              {
 | 
						|
                begin: /'/,
 | 
						|
                end: /'/,
 | 
						|
                contains: [ XML_ENTITIES ]
 | 
						|
              },
 | 
						|
              {
 | 
						|
                begin: /[^\s"'=<>`]+/
 | 
						|
              }
 | 
						|
            ]
 | 
						|
          }
 | 
						|
        ]
 | 
						|
      }
 | 
						|
    ]
 | 
						|
  };
 | 
						|
  return {
 | 
						|
    name: 'HTML, XML',
 | 
						|
    aliases: [
 | 
						|
      'html',
 | 
						|
      'xhtml',
 | 
						|
      'rss',
 | 
						|
      'atom',
 | 
						|
      'xjb',
 | 
						|
      'xsd',
 | 
						|
      'xsl',
 | 
						|
      'plist',
 | 
						|
      'wsf',
 | 
						|
      'svg'
 | 
						|
    ],
 | 
						|
    case_insensitive: true,
 | 
						|
    contains: [
 | 
						|
      {
 | 
						|
        className: 'meta',
 | 
						|
        begin: /<![a-z]/,
 | 
						|
        end: />/,
 | 
						|
        relevance: 10,
 | 
						|
        contains: [
 | 
						|
          XML_META_KEYWORDS,
 | 
						|
          QUOTE_META_STRING_MODE,
 | 
						|
          APOS_META_STRING_MODE,
 | 
						|
          XML_META_PAR_KEYWORDS,
 | 
						|
          {
 | 
						|
            begin: /\[/,
 | 
						|
            end: /\]/,
 | 
						|
            contains: [
 | 
						|
              {
 | 
						|
                className: 'meta',
 | 
						|
                begin: /<![a-z]/,
 | 
						|
                end: />/,
 | 
						|
                contains: [
 | 
						|
                  XML_META_KEYWORDS,
 | 
						|
                  XML_META_PAR_KEYWORDS,
 | 
						|
                  QUOTE_META_STRING_MODE,
 | 
						|
                  APOS_META_STRING_MODE
 | 
						|
                ]
 | 
						|
              }
 | 
						|
            ]
 | 
						|
          }
 | 
						|
        ]
 | 
						|
      },
 | 
						|
      hljs.COMMENT(
 | 
						|
        /<!--/,
 | 
						|
        /-->/,
 | 
						|
        {
 | 
						|
          relevance: 10
 | 
						|
        }
 | 
						|
      ),
 | 
						|
      {
 | 
						|
        begin: /<!\[CDATA\[/,
 | 
						|
        end: /\]\]>/,
 | 
						|
        relevance: 10
 | 
						|
      },
 | 
						|
      XML_ENTITIES,
 | 
						|
      {
 | 
						|
        className: 'meta',
 | 
						|
        begin: /<\?xml/,
 | 
						|
        end: /\?>/,
 | 
						|
        relevance: 10
 | 
						|
      },
 | 
						|
      {
 | 
						|
        className: 'tag',
 | 
						|
        /*
 | 
						|
        The lookahead pattern (?=...) ensures that 'begin' only matches
 | 
						|
        '<style' as a single word, followed by a whitespace or an
 | 
						|
        ending braket. The '$' is needed for the lexeme to be recognized
 | 
						|
        by hljs.subMode() that tests lexemes outside the stream.
 | 
						|
        */
 | 
						|
        begin: /<style(?=\s|>)/,
 | 
						|
        end: />/,
 | 
						|
        keywords: {
 | 
						|
          name: 'style'
 | 
						|
        },
 | 
						|
        contains: [ TAG_INTERNALS ],
 | 
						|
        starts: {
 | 
						|
          end: /<\/style>/,
 | 
						|
          returnEnd: true,
 | 
						|
          subLanguage: [
 | 
						|
            'css',
 | 
						|
            'xml'
 | 
						|
          ]
 | 
						|
        }
 | 
						|
      },
 | 
						|
      {
 | 
						|
        className: 'tag',
 | 
						|
        // See the comment in the <style tag about the lookahead pattern
 | 
						|
        begin: /<script(?=\s|>)/,
 | 
						|
        end: />/,
 | 
						|
        keywords: {
 | 
						|
          name: 'script'
 | 
						|
        },
 | 
						|
        contains: [ TAG_INTERNALS ],
 | 
						|
        starts: {
 | 
						|
          end: /<\/script>/,
 | 
						|
          returnEnd: true,
 | 
						|
          subLanguage: [
 | 
						|
            'javascript',
 | 
						|
            'handlebars',
 | 
						|
            'xml'
 | 
						|
          ]
 | 
						|
        }
 | 
						|
      },
 | 
						|
      // we need this for now for jSX
 | 
						|
      {
 | 
						|
        className: 'tag',
 | 
						|
        begin: /<>|<\/>/
 | 
						|
      },
 | 
						|
      // open tag
 | 
						|
      {
 | 
						|
        className: 'tag',
 | 
						|
        begin: concat(
 | 
						|
          /</,
 | 
						|
          lookahead(concat(
 | 
						|
            TAG_NAME_RE,
 | 
						|
            // <tag/>
 | 
						|
            // <tag>
 | 
						|
            // <tag ...
 | 
						|
            either(/\/>/, />/, /\s/)
 | 
						|
          ))
 | 
						|
        ),
 | 
						|
        end: /\/?>/,
 | 
						|
        contains: [
 | 
						|
          {
 | 
						|
            className: 'name',
 | 
						|
            begin: TAG_NAME_RE,
 | 
						|
            relevance: 0,
 | 
						|
            starts: TAG_INTERNALS
 | 
						|
          }
 | 
						|
        ]
 | 
						|
      },
 | 
						|
      // close tag
 | 
						|
      {
 | 
						|
        className: 'tag',
 | 
						|
        begin: concat(
 | 
						|
          /<\//,
 | 
						|
          lookahead(concat(
 | 
						|
            TAG_NAME_RE, />/
 | 
						|
          ))
 | 
						|
        ),
 | 
						|
        contains: [
 | 
						|
          {
 | 
						|
            className: 'name',
 | 
						|
            begin: TAG_NAME_RE,
 | 
						|
            relevance: 0
 | 
						|
          },
 | 
						|
          {
 | 
						|
            begin: />/,
 | 
						|
            relevance: 0,
 | 
						|
            endsParent: true
 | 
						|
          }
 | 
						|
        ]
 | 
						|
      }
 | 
						|
    ]
 | 
						|
  };
 | 
						|
}
 | 
						|
 | 
						|
module.exports = xml;
 |