/** * All parsing/transformation code goes here. All code here should be sync to ease testing. */ var Showdown = require('showdown'); var DOM = require('./dom.js').DOM; var htmlEscape = require('./dom.js').htmlEscape; var Example = require('./example.js').Example; var NEW_LINE = /\n\r?/; var globalID = 0; var fs = require('fs'); var fspath = require('path'); var markdown = new Showdown.converter({ extensions : ['table'] }); var shell = require('shelljs'); var gruntUtil = require('../../lib/grunt/utils.js'); exports.trim = trim; exports.metadata = metadata; exports.scenarios = scenarios; exports.merge = merge; exports.Doc = Doc; exports.ngVersions = function() { var line, versions = [], regex = /^v([1-9]\d*(?:\.\d+)+)$/; //only fetch >= 1.0.0 versions shell.exec('git tag', {silent: true}).output.split(/\s*\n\s*/) .forEach(function(line) { var matches = regex.exec(line); if(matches && matches.length > 0) { versions.push(matches[1]); } }); versions.push(exports.ngCurrentVersion().number); return versions; }; exports.ngCurrentVersion = function() { return gruntUtil.getVersion(); }; var BOOLEAN_ATTR = {}; ['multiple', 'selected', 'checked', 'disabled', 'readOnly', 'required'].forEach(function(value) { BOOLEAN_ATTR[value] = true; }); ////////////////////////////////////////////////////////// function Doc(text, file, line) { if (typeof text == 'object') { for ( var key in text) { this[key] = text[key]; } } else { this.text = text; this.file = file; this.line = line; } this.scenarios = this.scenarios || []; this.requires = this.requires || []; this.param = this.param || []; this.properties = this.properties || []; this.methods = this.methods || []; this.events = this.events || []; this.links = this.links || []; } Doc.METADATA_IGNORE = (function() { var words = fs.readFileSync(__dirname + '/ignore.words', 'utf8'); return words.toString().split(/[,\s\n\r]+/gm); })(); Doc.prototype = { keywords: function keywords() { var keywords = {}; var words = []; Doc.METADATA_IGNORE.forEach(function(ignore){ keywords[ignore] = true; }); function extractWords(text) { var tokens = text.toLowerCase().split(/[\.\s,`'"#]+/mg); tokens.forEach(function(key){ var match = key.match(/^((ng:|[\$_a-z])[\w\-_]+)/); if (match){ key = match[1]; if (!keywords[key]) { keywords[key] = true; words.push(key); } } }); } extractWords(this.text); this.properties.forEach(function(prop) { extractWords(prop.text || prop.description || ''); }); this.methods.forEach(function(method) { extractWords(method.text || method.description || ''); }); words.sort(); return words.join(' '); }, /** * Converts relative urls (without section) into absolute * Absolute url means url with section * * @example * - if the link is inside any api doc: * angular.widget -> api/angular.widget * * - if the link is inside any guid doc: * intro -> guide/intro * * @param {string} url Absolute or relative url * @returns {string} Absolute url */ convertUrlToAbsolute: function(url) { if (url.substr(-1) == '/') return url + 'index'; if (url.match(/\//)) return url; return this.section + '/' + url; }, markdown: function(text) { if (!text) return text; var self = this, IS_URL = /^(https?:\/\/|ftps?:\/\/|mailto:|\.|\/)/, IS_ANGULAR = /^(api\/)?(angular|ng|AUTO)\./, IS_HASH = /^#/, parts = trim(text).split(/(