125 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			125 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @dgService
							 | 
						||
| 
								 | 
							
								 * @description
							 | 
						||
| 
								 | 
							
								 * Parse the text from a cheatsheetItem tag into a cheatsheet item object
							 | 
						||
| 
								 | 
							
								 * The text must contain a syntax block followed by zero or more bold matchers and finally a
							 | 
						||
| 
								 | 
							
								 * description
							 | 
						||
| 
								 | 
							
								 * The syntax block and bold matchers must be wrapped in backticks and be separated by pipes.
							 | 
						||
| 
								 | 
							
								 * For example
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * ```
							 | 
						||
| 
								 | 
							
								 * `<div [ng-switch]="conditionExpression">
							 | 
						||
| 
								 | 
							
								 *   <template [ng-switch-when]="case1Exp">...</template>
							 | 
						||
| 
								 | 
							
								 *   <template ng-switch-when="case2LiteralString">...</template>
							 | 
						||
| 
								 | 
							
								 *   <template ng-switch-default>...</template>
							 | 
						||
| 
								 | 
							
								 * </div>`|`[ng-switch]`|`[ng-switch-when]`|`ng-switch-when`|`ng-switch-default`
							 | 
						||
| 
								 | 
							
								 * Conditionally swaps the contents of the div by selecting one of the embedded templates based on
							 | 
						||
| 
								 | 
							
								 * the current value of conditionExpression.
							 | 
						||
| 
								 | 
							
								 * ```
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * will be parsed into
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * ```
							 | 
						||
| 
								 | 
							
								 * {
							 | 
						||
| 
								 | 
							
								 *   syntax: '<div [ng-switch]="conditionExpression">\n'+
							 | 
						||
| 
								 | 
							
								 *           '  <template [ng-switch-when]="case1Exp">...</template>\n'+
							 | 
						||
| 
								 | 
							
								 *           '  <template ng-switch-when="case2LiteralString">...</template>\n'+
							 | 
						||
| 
								 | 
							
								 *           '  <template ng-switch-default>...</template>\n'+
							 | 
						||
| 
								 | 
							
								 *           '</div>',
							 | 
						||
| 
								 | 
							
								 *   bold: ['[ng-switch]', '[ng-switch-when]', 'ng-switch-when', 'ng-switch-default'],
							 | 
						||
| 
								 | 
							
								 *   description: 'Conditionally swaps the contents of the div by selecting one of the embedded
							 | 
						||
| 
								 | 
							
								 * templates based on the current value of conditionExpression.'
							 | 
						||
| 
								 | 
							
								 * }
							 | 
						||
| 
								 | 
							
								 * ```
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								module.exports =
							 | 
						||
| 
								 | 
							
								    function cheatsheetItemParser(targetEnvironments) {
							 | 
						||
| 
								 | 
							
								  return function(text) {
							 | 
						||
| 
								 | 
							
								    var fields = getFields(text, ['syntax', 'description']);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    var item = {syntax: '', bold: [], description: ''};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    fields.forEach(function(field) {
							 | 
						||
| 
								 | 
							
								      if (!field.languages || targetEnvironments.someActive(field.languages)) {
							 | 
						||
| 
								 | 
							
								        switch (field.name) {
							 | 
						||
| 
								 | 
							
								          case 'syntax':
							 | 
						||
| 
								 | 
							
								            parseSyntax(field.value.trim());
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								          case 'description':
							 | 
						||
| 
								 | 
							
								            item.description = field.value.trim();
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return item;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function parseSyntax(text) {
							 | 
						||
| 
								 | 
							
								      var index = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (text.charAt(index) !== '`') throw new Error('item syntax must start with a backtick');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      var start = index + 1;
							 | 
						||
| 
								 | 
							
								      index = text.indexOf('`', start);
							 | 
						||
| 
								 | 
							
								      if (index === -1) throw new Error('item syntax must end with a backtick');
							 | 
						||
| 
								 | 
							
								      item.syntax = text.substring(start, index);
							 | 
						||
| 
								 | 
							
								      start = index + 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // skip to next pipe
							 | 
						||
| 
								 | 
							
								      while (index < text.length && text.charAt(index) !== '|') index += 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      while (text.charAt(start) === '|') {
							 | 
						||
| 
								 | 
							
								        start += 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // skip whitespace
							 | 
						||
| 
								 | 
							
								        while (start < text.length && /\s/.test(text.charAt(start))) start++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (text.charAt(start) !== '`') throw new Error('bold matcher must start with a backtick');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        start += 1;
							 | 
						||
| 
								 | 
							
								        index = text.indexOf('`', start);
							 | 
						||
| 
								 | 
							
								        if (index === -1) throw new Error('bold matcher must end with a backtick');
							 | 
						||
| 
								 | 
							
								        item.bold.push(text.substring(start, index));
							 | 
						||
| 
								 | 
							
								        start = index + 1;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (start !== text.length) {
							 | 
						||
| 
								 | 
							
								        throw new Error(
							 | 
						||
| 
								 | 
							
								            'syntax field must only contain a syntax code block and zero or more bold ' +
							 | 
						||
| 
								 | 
							
								            'matcher code blocks, delimited by pipes.\n' +
							 | 
						||
| 
								 | 
							
								            'Instead it was "' + text + '"');
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function getFields(text, fieldNames) {
							 | 
						||
| 
								 | 
							
								  var FIELD_START = /^([^:(]+)\(?([^)]+)?\)?:$/;
							 | 
						||
| 
								 | 
							
								  var lines = text.split('\n');
							 | 
						||
| 
								 | 
							
								  var fields = [];
							 | 
						||
| 
								 | 
							
								  var field, line;
							 | 
						||
| 
								 | 
							
								  while (lines.length) {
							 | 
						||
| 
								 | 
							
								    line = lines.shift();
							 | 
						||
| 
								 | 
							
								    var match = FIELD_START.exec(line);
							 | 
						||
| 
								 | 
							
								    if (match && fieldNames.indexOf(match[1]) !== -1) {
							 | 
						||
| 
								 | 
							
								      // start new field
							 | 
						||
| 
								 | 
							
								      if (field) {
							 | 
						||
| 
								 | 
							
								        fields.push(field);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      field = {name: match[1], languages: (match[2] && match[2].split(' ')), value: ''};
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      if (!field)
							 | 
						||
| 
								 | 
							
								        throw new Error(
							 | 
						||
| 
								 | 
							
								            'item must start with one of the following field specifiers:\n' +
							 | 
						||
| 
								 | 
							
								            fieldNames.map(function(field) { return field + ':'; }).join('\n') + '\n' +
							 | 
						||
| 
								 | 
							
								            'but instead it contained: "' + text + '"');
							 | 
						||
| 
								 | 
							
								      field.value += line + '\n';
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (field) {
							 | 
						||
| 
								 | 
							
								    fields.push(field);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return fields;
							 | 
						||
| 
								 | 
							
								}
							 |